From 7aecf037ae56b32e62b09335f3708cc1be515b0e Mon Sep 17 00:00:00 2001 From: qgarnier Date: Fri, 30 Jun 2017 15:23:13 +0200 Subject: [PATCH] working on docker plugin --- .../cloud/docker/custom/dockerapi.pm | 218 ------------ centreon-plugins/cloud/docker/mode/blockio.pm | 219 ------------ .../cloud/docker/mode/containerstate.pm | 226 ------------ centreon-plugins/cloud/docker/mode/cpu.pm | 201 ----------- centreon-plugins/cloud/docker/mode/image.pm | 225 ------------ centreon-plugins/cloud/docker/mode/info.pm | 108 ------ .../cloud/docker/mode/listcontainers.pm | 154 -------- .../cloud/docker/mode/listnodes.pm | 154 -------- centreon-plugins/cloud/docker/mode/memory.pm | 175 ---------- .../cloud/docker/mode/nodestate.pm | 159 --------- centreon-plugins/cloud/docker/mode/traffic.pm | 218 ------------ .../cloud/docker/restapi/custom/api.pm | 328 ++++++++++++++++++ .../docker/restapi/mode/containerusage.pm | 237 +++++++++++++ .../cloud/docker/{ => restapi}/plugin.pm | 16 +- 14 files changed, 569 insertions(+), 2069 deletions(-) delete mode 100644 centreon-plugins/cloud/docker/custom/dockerapi.pm delete mode 100644 centreon-plugins/cloud/docker/mode/blockio.pm delete mode 100644 centreon-plugins/cloud/docker/mode/containerstate.pm delete mode 100644 centreon-plugins/cloud/docker/mode/cpu.pm delete mode 100644 centreon-plugins/cloud/docker/mode/image.pm delete mode 100644 centreon-plugins/cloud/docker/mode/info.pm delete mode 100644 centreon-plugins/cloud/docker/mode/listcontainers.pm delete mode 100644 centreon-plugins/cloud/docker/mode/listnodes.pm delete mode 100644 centreon-plugins/cloud/docker/mode/memory.pm delete mode 100644 centreon-plugins/cloud/docker/mode/nodestate.pm delete mode 100644 centreon-plugins/cloud/docker/mode/traffic.pm create mode 100644 centreon-plugins/cloud/docker/restapi/custom/api.pm create mode 100644 centreon-plugins/cloud/docker/restapi/mode/containerusage.pm rename centreon-plugins/cloud/docker/{ => restapi}/plugin.pm (60%) diff --git a/centreon-plugins/cloud/docker/custom/dockerapi.pm b/centreon-plugins/cloud/docker/custom/dockerapi.pm deleted file mode 100644 index c7a15182c..000000000 --- a/centreon-plugins/cloud/docker/custom/dockerapi.pm +++ /dev/null @@ -1,218 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::custom::dockerapi; - -use strict; -use warnings; -use centreon::plugins::misc; -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' }, - "proto:s" => { name => 'proto' }, - "credentials" => { name => 'credentials' }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "proxyurl:s" => { name => 'proxyurl' }, - "proxypac:s" => { name => 'proxypac' }, - "timeout:s" => { name => 'timeout' }, - "ssl:s" => { name => 'ssl' }, - "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' }, - }); - } - $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(output => $self->{output}); - - 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) = @_; - - # Manage default value - 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) = @_; - - if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { - $self->{output}->add_option_msg(short_msg => "You need to specify --hostname option."); - $self->{output}->option_exit(); - } - if (!defined($self->{option_results}->{proto}) || $self->{option_results}->{proto} eq '') { - $self->{output}->add_option_msg(short_msg => "You need to specify --proto option."); - $self->{output}->option_exit(); - } - -} - -sub api_request { - my ($self, %options) = @_; - - $self->{option_results}->{url_path} = $options{urlpath}; - $self->{option_results}->{port} = $options{port}; - $self->{method} = 'GET'; - $self->{option_results}->{get_param} = []; - push @{$self->{option_results}->{get_param}}, "all=true", "stream=false"; - - $self->{http}->set_options(%{$self->{option_results}}); - - my $webcontent; - my $jsoncontent = $self->{http}->request(method => $self->{method}); - - my $json = JSON->new; - - eval { - $webcontent = $json->decode($jsoncontent); - }; - - if ($@) { - $self->{output}->add_option_msg(short_msg => "Cannot retrieve any information"); - $self->{output}->option_exit(); - } - - return $webcontent; -} - -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 webserver host - -=item B<--proto> - -Specify https if needed (Default: 'http') - -=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<--proxyurl> - -Proxy URL - -=item B<--proxypac> - -Proxy pac file (can be an url or local file) - -=item B<--timeout> - -Threshold for HTTP timeout (Default: 5) - -=item B<--ssl> - -Specify SSL version (example : 'sslv3', 'tlsv1'...) - -=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 diff --git a/centreon-plugins/cloud/docker/mode/blockio.pm b/centreon-plugins/cloud/docker/mode/blockio.pm deleted file mode 100644 index 267c20c71..000000000 --- a/centreon-plugins/cloud/docker/mode/blockio.pm +++ /dev/null @@ -1,219 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::blockio; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; -use centreon::plugins::http; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "warning-read:s" => { name => 'warning-read' }, - "critical-read:s" => { name => 'critical-read' }, - "warning-write:s" => { name => 'warning-write' }, - "critical-write:s" => { name => 'critical-write' }, - }); - - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - $self->{http} = centreon::plugins::http->new(output => $self->{output}); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{name})) && (defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - if ((!defined($self->{option_results}->{name})) && (!defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - 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 'write' 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->{http}->set_options(%{$self->{option_results}}); - $self->{statefile_value}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - - my $new_datas = {}; - - if (defined($self->{option_results}->{id})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{id} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } elsif (defined($self->{option_results}->{name})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{name} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } - - my $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/stats"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/stats"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my $read_bytes = $webcontent->{blkio_stats}->{io_service_bytes_recursive}->[0]->{value}; - my $write_bytes = $webcontent->{blkio_stats}->{io_service_bytes_recursive}->[1]->{value}; - $new_datas->{read_bytes} = $read_bytes; - $new_datas->{write_bytes} = $write_bytes; - $new_datas->{last_timestamp} = time(); - my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); - - # First execution - if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); - $self->{statefile_value}->write(data => $new_datas); - $self->{output}->display(); - $self->{output}->exit(); - } - - my $time_delta = $new_datas->{last_timestamp} - $old_timestamp; - if ($time_delta <= 0) { - # At least one second. two fast calls ;) - $time_delta = 1; - } - - my $old_read_bytes = $self->{statefile_value}->get(name => 'read_bytes'); - my $old_write_bytes = $self->{statefile_value}->get(name => 'write_bytes'); - - if ($new_datas->{read_bytes} < $old_read_bytes) { - # We set 0. Has reboot. - $old_read_bytes = 0; - } - if ($new_datas->{write_bytes} < $old_write_bytes) { - # We set 0. Has reboot. - $old_write_bytes = 0; - } - - my $delta_read_bytes = $read_bytes - $old_read_bytes; - my $delta_write_bytes = $write_bytes - $old_write_bytes; - my $read_absolute_per_sec = $delta_read_bytes / $time_delta; - my $write_absolute_per_sec = $delta_write_bytes / $time_delta; - - my $exit1 = $self->{perfdata}->threshold_check(value => $read_absolute_per_sec, threshold => [ { label => 'critical-read', 'exit_litteral' => 'critical' }, { label => 'warning-read', exit_litteral => 'warning' } ]); - my $exit2 = $self->{perfdata}->threshold_check(value => $write_absolute_per_sec, threshold => [ { label => 'critical-write', 'exit_litteral' => 'critical' }, { label => 'warning-write', exit_litteral => 'warning' } ]); - - my ($read_value, $read_unit) = $self->{perfdata}->change_bytes(value => $read_absolute_per_sec, network => 1); - my ($write_value, $write_unit) = $self->{perfdata}->change_bytes(value => $write_absolute_per_sec, network => 1); - my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Read I/O : %s/s, Write I/O : %s/s", - $read_value . $read_unit, - $write_value . $write_unit)); - - $self->{output}->perfdata_add(label => 'read_io', unit => 'B/s', - value => sprintf("%.2f", $read_absolute_per_sec), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-read'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-read'), - min => 0); - $self->{output}->perfdata_add(label => 'write_io', unit => 'B/s', - value => sprintf("%.2f", $write_absolute_per_sec), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-write'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-write'), - min => 0); - - $self->{statefile_value}->write(data => $new_datas); - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's Block I/O usage - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one container's id - -=item B<--name> - -Specify one container's name - -=head2 MODE OPTIONS - -=item B<--warning-read> - -Threshold warning in B/s for Read I/O. - -=item B<--critical-read> - -Threshold critical in B/s for Read I/O. - -=item B<--warning-write> - -Threshold warning in B/s for Write I/O. - -=item B<--critical-write> - -Threshold critical in B/s for Write I/O. - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/containerstate.pm b/centreon-plugins/cloud/docker/mode/containerstate.pm deleted file mode 100644 index 9d5850fcb..000000000 --- a/centreon-plugins/cloud/docker/mode/containerstate.pm +++ /dev/null @@ -1,226 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::containerstate; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; - -my $thresholds = { - state => [ - ['Running', 'OK'], - ['Paused', 'WARNING'], - ['Restarting', 'WARNING'], - ['OOMKilled', 'CRITICAL'], - ['Dead', 'CRITICAL'], - ['Exited', 'CRITICAL'], - ], -}; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "threshold-overload:s@" => { name => 'threshold_overload' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{name})) && ($self->{option_results}->{name} eq '')) { - $self->{output}->add_option_msg(short_msg => "You need to specify the name option"); - $self->{output}->option_exit(); - } - - if ((defined($self->{option_results}->{id})) && ($self->{option_results}->{id} eq '')) { - $self->{output}->add_option_msg(short_msg => "You need to specify the id 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) = ($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}; - } -} - -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 $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/json"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/json"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my ($result,$containername,$containertime); - my $exit = 'OK'; - - if (defined($self->{option_results}->{id}) || defined($self->{option_results}->{name})) { - while ( my ($keys,$values) = each(%{$webcontent->{State}})) { - # Why not set a variable that contains the state? - if ($values eq 'true') { - $result = $keys; - $containername = $webcontent->{Name}; - $containername =~ s/^\///; - my ( $y, $m, $d, $h, $mi, $s ) = $webcontent->{State}->{StartedAt} =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/; - $containertime = $y."-".$m."-".$d." ".$h.":".$mi.":".$s; - last; - } - } - - $exit = $self->get_severity(section => 'state', value => $result); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Container %s is %s (started since %s)", $containername, $result, $containertime)); - } else { - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("All containers are in Running state")); - - my ($nbrunning,$nbpaused,$nbexited) = '0'; - - foreach my $val (@$webcontent) { - $containername = $val->{Names}->[0]; - $containername =~ s/^\///; - - # Thanks to Docker API for the paused state... - if (($val->{Status} =~ m/^Up/) && ($val->{Status} =~ m/^(?:(?!Paused).)*$/)) { - $result = 'Running'; - $nbrunning++; - } elsif ($val->{Status} =~ m/^Exited/) { - $result = 'Exited'; - $nbexited++; - } elsif ($val->{Status} =~ m/\(Paused\)$/) { - $result = 'Paused'; - $nbpaused++; - } - - my $tmp_exit = $self->get_severity(section => 'state', value => $result); - $exit = $self->{output}->get_most_critical(status => [ $tmp_exit, $exit ]); - if (!$self->{output}->is_status(value => $tmp_exit, compare => 'OK', litteral => 1)) { - $self->{output}->output_add(long_msg => sprintf("Containers %s is in %s state", - $containername, $result)); - } - } - - if (!$self->{output}->is_status(value => $exit, compare => 'OK', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Some containers are in wrong state")); - } - $self->{output}->perfdata_add(label => "running", - value => $nbrunning, - min => 0, - ); - $self->{output}->perfdata_add(label => "paused", - value => $nbpaused, - min => 0, - ); - $self->{output}->perfdata_add(label => "exited", - value => $nbexited, - min => 0, - ); - } - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's state - -=head2 DOCKER OPTIONS - -item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one container's id - -=item B<--name> - -Specify one container's name - -=head2 MODE OPTIONS - -=item B<--threshold-overload> - -Set to overload default threshold values (syntax: section,status,regexp) -It used before default thresholds (order stays). -Example: --threshold-overload='state,CRITICAL,^(?!(Paused)$)' - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/cpu.pm b/centreon-plugins/cloud/docker/mode/cpu.pm deleted file mode 100644 index 32e0b48f1..000000000 --- a/centreon-plugins/cloud/docker/mode/cpu.pm +++ /dev/null @@ -1,201 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::cpu; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; -use centreon::plugins::http; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - }); - - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - $self->{http} = centreon::plugins::http->new(output => $self->{output}); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{name})) && (defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - - if ((!defined($self->{option_results}->{name})) && (!defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id 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->{http}->set_options(%{$self->{option_results}}); - $self->{statefile_value}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{id})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{id} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } elsif (defined($self->{option_results}->{name})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{name} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } - - my $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/stats"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/stats"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my $cpu_totalusage = $webcontent->{cpu_stats}->{cpu_usage}->{total_usage}; - my $cpu_systemusage = $webcontent->{cpu_stats}->{system_cpu_usage}; - my @cpu_number = @{$webcontent->{cpu_stats}->{cpu_usage}->{percpu_usage}}; - my $cpu_throttledtime = $webcontent->{cpu_stats}->{throttling_data}->{throttled_time}; - - my $new_datas = {}; - $new_datas->{cpu_totalusage} = $cpu_totalusage; - $new_datas->{cpu_systemusage} = $cpu_systemusage; - $new_datas->{cpu_throttledtime} = $cpu_throttledtime; - my $old_cpu_totalusage = $self->{statefile_value}->get(name => 'cpu_totalusage'); - my $old_cpu_systemusage = $self->{statefile_value}->get(name => 'cpu_systemusage'); - my $old_cpu_throttledtime = $self->{statefile_value}->get(name => 'cpu_throttledtime'); - - if ((!defined($old_cpu_totalusage)) || (!defined($old_cpu_systemusage)) || (!defined($old_cpu_throttledtime))) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); - $self->{statefile_value}->write(data => $new_datas); - $self->{output}->display(); - $self->{output}->exit(); - } - - if ($new_datas->{cpu_totalusage} < $old_cpu_totalusage) { - # We set 0. Has reboot. - $old_cpu_totalusage = 0; - } - if ($new_datas->{cpu_systemusage} < $old_cpu_systemusage) { - # We set 0. Has reboot. - $old_cpu_systemusage = 0; - } - - if ($new_datas->{cpu_throttledtime} < $old_cpu_throttledtime) { - # We set 0. Has reboot. - $old_cpu_throttledtime = 0; - } - - my $delta_totalusage = $cpu_totalusage - $old_cpu_totalusage; - my $delta_systemusage = $cpu_systemusage - $old_cpu_systemusage; - my $delta_throttledtime = $cpu_throttledtime - $old_cpu_throttledtime; - # Nano second to second - my $throttledtime = $delta_throttledtime / 10 ** 9; - my $prct_cpu = (($delta_totalusage / $delta_systemusage) * scalar(@cpu_number)) * 100; - - my $exit = $self->{perfdata}->threshold_check(value => $prct_cpu, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("CPU Usage is %.2f%% (Throttled Time: %.3fs)", $prct_cpu, $throttledtime)); - - $self->{output}->perfdata_add(label => "cpu", unit => '%', - value => $prct_cpu, - 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 => "throttled", unit => 's', - value => $throttledtime, - min => 0, - ); - - - $self->{statefile_value}->write(data => $new_datas); - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's CPU usage - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one container's id - -=item B<--name> - -Specify one container's name - -=head2 MODE OPTIONS - -=item B<--warning> - -Threshold warning in percent. - -=item B<--critical> - -Threshold critical in percent. - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/image.pm b/centreon-plugins/cloud/docker/mode/image.pm deleted file mode 100644 index 1a8e5ffa0..000000000 --- a/centreon-plugins/cloud/docker/mode/image.pm +++ /dev/null @@ -1,225 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::image; - -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; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "image:s" => { name => 'image' }, - "registry-hostname:s" => { name => 'registry_hostname' }, - "registry-proto:s" => { name => 'registry_proto', default => 'https' }, - "registry-port:s" => { name => 'registry_port' }, - "credentials" => { name => 'credentials' }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "ssl:s" => { name => 'ssl', }, - "cert-file:s" => { name => 'cert_file' }, - "key-file:s" => { name => 'key_file' }, - "cacert-file:s" => { name => 'cacert_file' }, - "timeout:s" => { name => 'timeout' }, - }); - - $self->{http} = centreon::plugins::http->new(output => $self->{output}); - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{name})) && (defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - - if ((!defined($self->{option_results}->{name})) && (!defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{image})) { - $self->{output}->add_option_msg(short_msg => "Please set the image option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{registry_hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the registry-hostname option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{registry_proto})) { - $self->{output}->add_option_msg(short_msg => "Please set the registry-proto option"); - $self->{output}->option_exit(); - } - - $self->{http}->set_options(%{$self->{option_results}}); -} - -sub run { - my ($self, %options) = @_; - - my ($jsoncontent, $webcontent, $webcontent2); - - my $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/stats"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/stats"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my $container_id = $webcontent->{Image}; - - $self->{option_results}->{url_path} = "/v1/repositories/".$self->{option_results}->{image}."/tags"; - $self->{option_results}->{port} = $self->{option_results}->{registry_port}; - $self->{option_results}->{proto} = $self->{option_results}->{registry_proto}; - $self->{option_results}->{hostname} = $self->{option_results}->{registry_hostname}; - $self->{http}->set_options(%{$self->{option_results}}); - - $jsoncontent = $self->{http}->request(); - - my $json2 = JSON->new; - - eval { - $webcontent2 = $json2->decode($jsoncontent); - }; - - if ($@) { - $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); - $self->{output}->option_exit(); - } - - my $result; - - foreach (@{$webcontent2}) { - if (($container_id =~ /^$_->{layer}\w+$/)) { - $result="1"; - last; - } - } - - if ($result eq "1") { - $self->{output}->output_add(severity => "OK", - short_msg => sprintf("Container's image and Registry image are identical")); - } else { - $self->{output}->output_add(severity => "CRITICAL", - short_msg => sprintf("Container's image and Registry image are different")); - } - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's image viability with a registry - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=item B<--id> - -Specify the container's id - -=item B<--name> - -Specify the container's name - -=head2 MODE OPTIONS - -=item B<--image> - -Specify the image's name - -=item B<--registry-hostname> - -IP Addr/FQDN of Docker's Registry - -=item B<--registry-port> - -Port used by Docker's Registry - -=item B<--registry-proto> - -Specify https if needed (Default: 'https') - -=item B<--credentials> - -Specify this option if you access webpage over basic authentification - -=item B<--username> - -Specify username - -=item B<--password> - -Specify password - -=item B<--ssl> - -Specify SSL version (example : 'sslv3', 'tlsv1'...) - -=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<--timeout> - -Threshold for HTTP timeout (Default: 3) - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/info.pm b/centreon-plugins/cloud/docker/mode/info.pm deleted file mode 100644 index 3793c3fdf..000000000 --- a/centreon-plugins/cloud/docker/mode/info.pm +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::info; - -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; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' } - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); -} - -sub run { - my ($self, %options) = @_; - - my $urlpath = "/info"; - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("Docker is running")); - - $self->{output}->perfdata_add(label => "containers", - value => $webcontent->{Containers}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "events_listener", - value => $webcontent->{NEventsListener}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "file_descriptor", - value => $webcontent->{NFd}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "go_routines", - value => $webcontent->{NGoroutines}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "images", - value => $webcontent->{Images}, - min => 0, - ); - - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Docker information - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/listcontainers.pm b/centreon-plugins/cloud/docker/mode/listcontainers.pm deleted file mode 100644 index 6223f8808..000000000 --- a/centreon-plugins/cloud/docker/mode/listcontainers.pm +++ /dev/null @@ -1,154 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::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; - - $self->{version} = '1.2'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "exclude:s" => { name => 'exclude' }, - }); - - $self->{container_infos} = (); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); -} - -sub check_exclude { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)${options{status}}(\s|,|$)/) { - $self->{output}->output_add(long_msg => sprintf("Skipping ${options{status}} container.")); - return 1; - } -return 0; -} - -sub listcontainer_request { - my ($self, %options) = @_; - - my $urlpath = "/containers/json"; - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - foreach my $val (@$webcontent) { - my $containerstate; - if (($val->{Status} =~ m/^Up/) && ($val->{Status} =~ m/^(?:(?!Paused).)*$/)) { - return if ($self->check_exclude(status => 'Running')); - $containerstate = 'Running'; - } elsif ($val->{Status} =~ m/^Exited/) { - return if ($self->check_exclude(status => 'Exited')); - $containerstate = 'Exited'; - } elsif ($val->{Status} =~ m/\(Paused\)$/) { - return if ($self->check_exclude(status => 'Paused')); - $containerstate = 'Paused'; - } - my $containername = $val->{Names}->[0]; - $containername =~ s/^\///; - $self->{container_infos}->{$containername}->{id} = $val->{Id}; - $self->{container_infos}->{$containername}->{image} = $val->{Image}; - $self->{container_infos}->{$containername}->{state} = $containerstate; - } -} - -sub disco_format { - my ($self, %options) = @_; - - my $names = ['name', 'id', 'image', 'state']; - $self->{output}->add_disco_format(elements => $names); -} - -sub disco_show { - my ($self, %options) = @_; - - $self->listcontainer_request(%options); - - foreach my $containername (keys %{$self->{container_infos}}) { - $self->{output}->add_disco_entry(name => $containername, - id => $self->{container_infos}->{$containername}->{id}, - image => $self->{container_infos}->{$containername}->{image}, - state => $self->{container_infos}->{$containername}->{state}, - ); - } -} - -sub run { - my ($self, %options) = @_; - - $self->listcontainer_request(%options); - - foreach my $containername (keys %{$self->{container_infos}}) { - $self->{output}->output_add(long_msg => sprintf("%s [id = %s , image = %s, state = %s]", - $containername, - $self->{container_infos}->{$containername}->{id}, - $self->{container_infos}->{$containername}->{image}, - $self->{container_infos}->{$containername}->{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(); - -} - -1; - -__END__ - -=head1 MODE - -List Docker containers - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=head2 MODE OPTIONS - -=item B<--exlude> - -Exclude specific container's state (comma seperated list) (Example: --exclude=Paused,Running) - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/listnodes.pm b/centreon-plugins/cloud/docker/mode/listnodes.pm deleted file mode 100644 index 56a69b525..000000000 --- a/centreon-plugins/cloud/docker/mode/listnodes.pm +++ /dev/null @@ -1,154 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::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; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "exclude:s" => { name => 'exclude' }, - }); - - $self->{node_infos} = (); - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); -} - -sub check_exclude { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)${options{status}}(\s|,|$)/) { - $self->{output}->output_add(long_msg => sprintf("Skipping ${options{status}} nodes.")); - return 1; - } -return 0; -} - -sub listnode_request { - my ($self, %options) = @_; - - my $urlpath = "/nodes"; - my $port = $self->{option_results}->{port}; - - my $nodeapi = $options{custom}; - my $webcontent = $nodeapi->api_request(urlpath => $urlpath, - port => $port); - - foreach my $val (@$webcontent) { - next if ($self->check_exclude(status => $val->{Status}->{State})); - my $nodeid = $val->{ID}; - $self->{node_infos}->{$nodeid}->{hostname} = $val->{Description}->{Hostname}; - $self->{node_infos}->{$nodeid}->{role} = $val->{Spec}->{Role}; - $self->{node_infos}->{$nodeid}->{availability} = $val->{Spec}->{Availability}; - $self->{node_infos}->{$nodeid}->{state} = $val->{Status}->{State}; - if ($val->{Spec}->{Role} eq 'manager') { - $self->{node_infos}->{$nodeid}->{reachability} = $val->{ManagerStatus}->{Reachability}; - } else { - $self->{node_infos}->{$nodeid}->{reachability} = ''; - } - - } -} - -sub disco_format { - my ($self, %options) = @_; - - my $names = ['id', 'hostname', 'role', 'state', 'availability', 'reachability']; - $self->{output}->add_disco_format(elements => $names); -} - -sub disco_show { - my ($self, %options) = @_; - - $self->listnode_request(%options); - - foreach my $nodeid (keys %{$self->{node_infos}}) { - $self->{output}->add_disco_entry(id => $nodeid, - hostname => $self->{node_infos}->{$nodeid}->{hostname}, - role => $self->{node_infos}->{$nodeid}->{role}, - state => $self->{node_infos}->{$nodeid}->{state}, - availability => $self->{node_infos}->{$nodeid}->{availability}, - reachability => $self->{node_infos}->{$nodeid}->{reachability}, - ); - } -} - -sub run { - my ($self, %options) = @_; - - $self->listnode_request(%options); - - foreach my $nodeid (keys %{$self->{node_infos}}) { - $self->{output}->output_add(long_msg => sprintf("%s [hostname = %s , role = %s, state = %s, availability = %s, reachability = %s]", - $nodeid, - $self->{node_infos}->{$nodeid}->{hostname}, - $self->{node_infos}->{$nodeid}->{role}, - $self->{node_infos}->{$nodeid}->{state}, - $self->{node_infos}->{$nodeid}->{availability}, - $self->{node_infos}->{$nodeid}->{reachability})); - } - - $self->{output}->output_add(severity => 'OK', - short_msg => 'List Swarm nodes:'); - - $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); - $self->{output}->exit(); - - exit 0; -} - -1; - -__END__ - -=head1 MODE - -List Docker Swarm nodes - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=head2 MODE OPTIONS - -=item B<--exlude> - -Exclude specific node's state (comma seperated list) (Example: --exclude=disconnected) - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/memory.pm b/centreon-plugins/cloud/docker/mode/memory.pm deleted file mode 100644 index 1b8dd8317..000000000 --- a/centreon-plugins/cloud/docker/mode/memory.pm +++ /dev/null @@ -1,175 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::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; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "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}->{name})) && (defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - - if ((!defined($self->{option_results}->{name})) && (!defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id 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(); - } -} - -sub run { - my ($self, %options) = @_; - - my $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/stats"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/stats"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my $total_size = $webcontent->{memory_stats}->{limit}; - my $memory_used = $webcontent->{memory_stats}->{usage}; - my $memory_free = $webcontent->{memory_stats}->{limit} - $webcontent->{memory_stats}->{usage}; - my $prct_used = $memory_used * 100 / $total_size; - my $prct_free = 100 - $prct_used; - my $failed_counter = $webcontent->{memory_stats}->{failcnt}; - my $memory_cached = $webcontent->{memory_stats}->{stats}->{cache}; - my $memory_rss = $webcontent->{memory_stats}->{stats}->{rss}; - - my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $total_size); - my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $memory_used); - my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $memory_free); - my ($cached_value, $cached_unit) = $self->{perfdata}->change_bytes(value => $memory_cached); - my ($rss_value, $rss_unit) = $self->{perfdata}->change_bytes(value => $memory_rss); - - - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Memory Total: %s Used: %s (%.2f%%) Free: %s %.2f%%) Cached: %s RSS: %s Failed: %s", - $total_value . " " . $total_unit, - $used_value . " " . $used_unit, $prct_used, - $free_value . " " . $free_unit, $prct_free, - $cached_value . " " . $cached_unit, - $rss_value . " " . $rss_unit, - $failed_counter) - ); - - $self->{output}->perfdata_add(label => "used", - value => $webcontent->{memory_stats}->{usage}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $total_size, cast_int => 1), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $total_size, cast_int => 1), - min => 0, - max => $webcontent->{memory_stats}->{limit}, - ); - - $self->{output}->perfdata_add(label => "cached", - value => $webcontent->{memory_stats}->{stats}->{cache}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "rss", - value => $webcontent->{memory_stats}->{stats}->{rss}, - min => 0, - ); - - $self->{output}->perfdata_add(label => "failed", - value => $webcontent->{memory_stats}->{failcnt}, - min => 0, - ); - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's memory usage - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one container's id - -=item B<--name> - -Specify one container's name - -=head2 MODE OPTIONS - -=item B<--warning> - -Threshold warning in percent. - -=item B<--critical> - -Threshold critical in percent. - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/nodestate.pm b/centreon-plugins/cloud/docker/mode/nodestate.pm deleted file mode 100644 index 9f7e6574e..000000000 --- a/centreon-plugins/cloud/docker/mode/nodestate.pm +++ /dev/null @@ -1,159 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::nodestate; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; - -my $thresholds = { - state => [ - ['ready', 'OK'], - ['disconnected', 'WARNING'], - ['down', 'CRITICAL'], - ['unknown', 'UNKNOWN'], - ], -}; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "id:s" => { name => 'id' }, - "threshold-overload:s@" => { name => 'threshold_overload' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{id})) && ($self->{option_results}->{id} eq '')) { - $self->{output}->add_option_msg(short_msg => "You need to specify the id 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) = ($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}; - } -} - -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 $urlpath = "/nodes/".$self->{option_results}->{id}; - my $port = $self->{option_results}->{port}; - my $nodeapi = $options{custom}; - - my $webcontent = $nodeapi->api_request(urlpath => $urlpath, - port => $port); - - my $exit = $self->get_severity(section => 'state', value => $webcontent->{Status}->{State}); - - if (defined($webcontent->{ManagerStatus}->{Reachability})) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("%s node is %s (Availability: %s - Reachability: %s)", - $webcontent->{Spec}->{Role}, - $webcontent->{Status}->{State}, - $webcontent->{Spec}->{Availability}, - $webcontent->{ManagerStatus}->{Reachability})); - } else { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("%s node is %s (Availability: %s)", - $webcontent->{Spec}->{Role}, - $webcontent->{Status}->{State}, - $webcontent->{Spec}->{Availability})); - } - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Swarm Node's state - -=head2 DOCKER OPTIONS - -item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one node's id - -=head2 MODE OPTIONS - -=item B<--threshold-overload> - -Set to overload default threshold values (syntax: section,status,regexp) -It used before default thresholds (order stays). -Example: --threshold-overload='state,CRITICAL,^(?!(disconnected)$)' - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/mode/traffic.pm b/centreon-plugins/cloud/docker/mode/traffic.pm deleted file mode 100644 index a183bf90b..000000000 --- a/centreon-plugins/cloud/docker/mode/traffic.pm +++ /dev/null @@ -1,218 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package cloud::docker::mode::traffic; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; -use centreon::plugins::http; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "port:s" => { name => 'port' }, - "name:s" => { name => 'name' }, - "id:s" => { name => 'id' }, - "warning-in:s" => { name => 'warning_in' }, - "critical-in:s" => { name => 'critical_in' }, - "warning-out:s" => { name => 'warning_out' }, - "critical-out:s" => { name => 'critical_out' }, - }); - - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - $self->{http} = centreon::plugins::http->new(output => $self->{output}); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if ((defined($self->{option_results}->{name})) && (defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - if ((!defined($self->{option_results}->{name})) && (!defined($self->{option_results}->{id}))) { - $self->{output}->add_option_msg(short_msg => "Please set the name or id option"); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'warning-in', value => $self->{option_results}->{warning_in})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning 'in' threshold '" . $self->{option_results}->{warning_in} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical-in', value => $self->{option_results}->{critical_in})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical 'in' threshold '" . $self->{option_results}->{critical_in} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'warning-out', value => $self->{option_results}->{warning_out})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning 'out' threshold '" . $self->{option_results}->{warning_out} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical-out', value => $self->{option_results}->{critical_out})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical 'out' threshold '" . $self->{option_results}->{critical_out} . "'."); - $self->{output}->option_exit(); - } - - $self->{http}->set_options(%{$self->{option_results}}); - $self->{statefile_value}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - - my $new_datas = {}; - - if (defined($self->{option_results}->{id})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{id} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } elsif (defined($self->{option_results}->{name})) { - $self->{statefile_value}->read(statefile => 'docker_' . $self->{option_results}->{name} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); - } - - my $urlpath; - if (defined($self->{option_results}->{id})) { - $urlpath = "/containers/".$self->{option_results}->{id}."/stats"; - } elsif (defined($self->{option_results}->{name})) { - $urlpath = "/containers/".$self->{option_results}->{name}."/stats"; - } - my $port = $self->{option_results}->{port}; - my $containerapi = $options{custom}; - - my $webcontent = $containerapi->api_request(urlpath => $urlpath, - port => $port); - - my $rx_bytes = $webcontent->{network}->{rx_bytes}; - my $tx_bytes = $webcontent->{network}->{tx_bytes}; - $new_datas->{rx_bytes} = $rx_bytes; - $new_datas->{tx_bytes} = $tx_bytes; - $new_datas->{last_timestamp} = time(); - my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); - - if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); - $self->{statefile_value}->write(data => $new_datas); - $self->{output}->display(); - $self->{output}->exit(); - } - - my $time_delta = $new_datas->{last_timestamp} - $old_timestamp; - if ($time_delta <= 0) { - # At least one second. two fast calls ;) - $time_delta = 1; - } - - my $old_rx_bytes = $self->{statefile_value}->get(name => 'rx_bytes'); - my $old_tx_bytes = $self->{statefile_value}->get(name => 'tx_bytes'); - - if ($new_datas->{rx_bytes} < $old_rx_bytes) { - # We set 0. Has reboot. - $old_rx_bytes = 0; - } - if ($new_datas->{tx_bytes} < $old_tx_bytes) { - # We set 0. Has reboot. - $old_tx_bytes = 0; - } - - my $delta_rx_bits = ($rx_bytes - $old_rx_bytes) * 8; - my $delta_tx_bits = ($tx_bytes - $old_tx_bytes) * 8; - my $rx_absolute_per_sec = $delta_rx_bits / $time_delta; - my $tx_absolute_per_sec = $delta_tx_bits / $time_delta; - - my $exit1 = $self->{perfdata}->threshold_check(value => $rx_absolute_per_sec, threshold => [ { label => 'critical-in', 'exit_litteral' => 'critical' }, { label => 'warning-in', exit_litteral => 'warning' } ]); - my $exit2 = $self->{perfdata}->threshold_check(value => $tx_absolute_per_sec, threshold => [ { label => 'critical-out', 'exit_litteral' => 'critical' }, { label => 'warning-out', exit_litteral => 'warning' } ]); - - my ($rx_value, $rx_unit) = $self->{perfdata}->change_bytes(value => $rx_absolute_per_sec, network => 1); - my ($tx_value, $tx_unit) = $self->{perfdata}->change_bytes(value => $tx_absolute_per_sec, network => 1); - my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Traffic In : %s/s, Out : %s/s", - $rx_value . $rx_unit, - $tx_value . $tx_unit)); - - $self->{output}->perfdata_add(label => 'traffic_in', unit => 'b/s', - value => sprintf("%.2f", $rx_absolute_per_sec), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-in'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-in'), - min => 0); - $self->{output}->perfdata_add(label => 'traffic_out', unit => 'b/s', - value => sprintf("%.2f", $tx_absolute_per_sec), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-out'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-out'), - min => 0); - - $self->{statefile_value}->write(data => $new_datas); - - $self->{output}->display(); - $self->{output}->exit(); - -} - -1; - -__END__ - -=head1 MODE - -Check Container's Network traffic usage - -=head2 DOCKER OPTIONS - -=item B<--port> - -Port used by Docker - -=item B<--id> - -Specify one container's id - -=item B<--name> - -Specify one container's name - -=head2 MODE OPTIONS - -=item B<--warning-in> - -Threshold warning in b/s for 'in' traffic. - -=item B<--critical-in> - -Threshold critical in b/s for 'in' traffic. - -=item B<--warning-out> - -Threshold warning in b/s for 'out' traffic. - -=item B<--critical-out> - -Threshold critical in b/s for 'out' traffic. - -=back - -=cut diff --git a/centreon-plugins/cloud/docker/restapi/custom/api.pm b/centreon-plugins/cloud/docker/restapi/custom/api.pm new file mode 100644 index 000000000..984466f22 --- /dev/null +++ b/centreon-plugins/cloud/docker/restapi/custom/api.pm @@ -0,0 +1,328 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::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' }, + "username:s" => { name => 'username' }, + "password:s" => { name => 'password' }, + "proxyurl:s" => { name => 'proxyurl' }, + "proxypac:s" => { name => 'proxypac' }, + "timeout:s" => { name => 'timeout', default => 10 }, + "ssl:s" => { name => 'ssl' }, + "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' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + + return $self; + +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +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) = @_; + # return 1 = ok still hostname + # return 0 = no hostname left + + $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->{http} = {}; + foreach my $node_name (@{$self->{hostname}}) { + if ($node_name ne '') { + $self->{http}->{$node_name} = centreon::plugins::http->new(output => $self->{output}); + $self->{options_results}->{hostname} = $node_name; + $self->{http}->{$node_name}->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_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_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 internal_api_list_containers { + my ($self, %options) = @_; + + my $response = $self->{http}->{$options{node_name}}->request( + url_path => '/containers/json?all=true', + critical_status => '', warning_status => ''); + my $containers; + eval { + $containers = JSON::XS->new->utf8->decode($response); + }; + if ($@) { + $containers = []; + $self->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}->{$options{node_name}}->request( + url_path => '/containers/' . $options{container_id} . '/stats?stream=false', + critical_status => '', warning_status => ''); + my $container_stats; + eval { + $container_stats = JSON::XS->new->utf8->decode($response); + }; + if ($@) { + $container_stats = {}; + $self->output_add(severity => 'UNKNOWN', + short_msg => "Node '$options{node_name}': cannot decode json get container stats response: $@"); + } + + return $container_stats; +} + +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 = {}; + foreach my $node_name (keys %{$self->{http}}) { + my $containers = $self->internal_api_list_containers(node_name => $node_name); + foreach my $container (@$containers) { + $content_total->{$container->{Id}} = { + State => $container->{State}, + NodeName => $node_name, + Name => join(':', @{$container->{Names}}), + }; + $content_total->{$container->{Id}}->{Stats} = $self->internal_api_get_container_stats(node_name => $node_name, container_id => $container->{Id}); + } + } + + 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 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<--proxyurl> + +Proxy URL + +=item B<--proxypac> + +Proxy pac file (can be an url or local file) + +=item B<--timeout> + +Threshold for HTTP timeout (Default: 10) + +=item B<--ssl> + +Specify SSL version (example : 'sslv3', 'tlsv1'...) + +=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. + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/cloud/docker/restapi/mode/containerusage.pm b/centreon-plugins/cloud/docker/restapi/mode/containerusage.pm new file mode 100644 index 000000000..7fc99c45a --- /dev/null +++ b/centreon-plugins/cloud/docker/restapi/mode/containerusage.pm @@ -0,0 +1,237 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::docker::restapi::mode::containerusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = '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 => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers are ok', skipped_code => { -11 => 1 } }, + ]; + + $self->{maps_counters}->{output_stream} = [ + { label => 'container-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 => $self->can('custom_status_threshold'), + } + }, + { label => 'traffic-in', set => { + key_values => [ { name => 'traffic_in', diff => 1 }, { name => 'name' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic In : %s %s/s', + perfdatas => [ + { label => 'traffic_in', value => 'traffic_in_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'traffic_out', diff => 1 }, { name => 'name' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic Out : %s %s/s', + perfdatas => [ + { label => 'traffic_out', value => 'traffic_out_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'dropped-in', set => { + key_values => [ { name => 'dropped_in', diff => 1 }, { name => 'name' } ], + output_template => 'Packets Dropped In : %s', + perfdatas => [ + { label => 'dropped_in', value => 'dropped_in_absolute', template => '%.2f', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-container-status:s" => { name => 'warning_container_status' }, + "critical-container-status:s" => { name => 'critical_container_status', default => '%{status} !~ /Connecting|Connected/i || %{error} !~ /none/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_containers_output { + my ($self, %options) = @_; + + return "Container '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_container_status', 'critical_container_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{containers} = {}; + my $result = $options{custom}->api_get_containers(); + use Data::Dumper; + print Data::Dumper::Dumper($result); + exit(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}} = { + display => $name, + status => $entry->{status}, + 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->{containers}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No container found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "docker_" . $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 container 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='^container-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-container-status> + +Set warning threshold for status (Default: -) +Can used special variables like: %{id}, %{name}, %{status}. + +=item B<--critical-container-status> + +Set critical threshold for status (Default: '%{status} !~ /Connecting|Connected/i'). +Can used special variables like: %{id}, %{name}, %{status}. + +=back + +=cut diff --git a/centreon-plugins/cloud/docker/plugin.pm b/centreon-plugins/cloud/docker/restapi/plugin.pm similarity index 60% rename from centreon-plugins/cloud/docker/plugin.pm rename to centreon-plugins/cloud/docker/restapi/plugin.pm index 26fb0da07..9356bacc4 100644 --- a/centreon-plugins/cloud/docker/plugin.pm +++ b/centreon-plugins/cloud/docker/restapi/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::plugin; +package cloud::docker::restapi::plugin; use strict; use warnings; @@ -31,19 +31,11 @@ sub new { $self->{version} = '0.3'; %{$self->{modes}} = ( - 'blockio' => 'cloud::docker::mode::blockio', - 'containerstate' => 'cloud::docker::mode::containerstate', - 'cpu' => 'cloud::docker::mode::cpu', - 'image' => 'cloud::docker::mode::image', - 'info' => 'cloud::docker::mode::info', - 'list-containers' => 'cloud::docker::mode::listcontainers', - 'list-nodes' => 'cloud::docker::mode::listnodes', - 'memory' => 'cloud::docker::mode::memory', - 'nodestate' => 'cloud::docker::mode::nodestate', - 'traffic' => 'cloud::docker::mode::traffic', + 'container-usage' => 'cloud::docker::restapi::mode::containerusage', + 'node-status' => 'cloud::docker::restapi::mode::nodestatus', ); - $self->{custom_modes}{dockerapi} = 'cloud::docker::custom::dockerapi'; + $self->{custom_modes}{api} = 'cloud::docker::restapi::custom::api'; return $self; }