diff --git a/cloud/docker/cadvisor/custom/api.pm b/cloud/cadvisor/restapi/custom/api.pm similarity index 92% rename from cloud/docker/cadvisor/custom/api.pm rename to cloud/cadvisor/restapi/custom/api.pm index 98c1aa271..dd905656b 100644 --- a/cloud/docker/cadvisor/custom/api.pm +++ b/cloud/cadvisor/restapi/custom/api.pm @@ -1,5 +1,5 @@ # -# Copyright 2018 Centreon (http://www.centreon.com/) +# 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 @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::cadvisor::custom::api; +package cloud::cadvisor::restapi::custom::api; use strict; use warnings; @@ -47,6 +47,7 @@ sub new { "hostname:s@" => { name => 'hostname' }, "port:s" => { name => 'port', default => 8080 }, "proto:s" => { name => 'proto', default => 'http' }, + "path:s" => { name => 'path', default => '/containers/docker/' }, "credentials" => { name => 'credentials' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, @@ -59,7 +60,7 @@ sub new { "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' }, + "api-version:s" => { name => 'api_version', default => 'v1.3' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -100,8 +101,6 @@ sub check_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(); @@ -134,7 +133,7 @@ sub internal_api_list_nodes { my ($self, %options) = @_; my $response = $self->{http}->{$options{node_name}}->request( - url_path => '/api/' . $self->{option_results}->{api_version} . '/containers/docker/', + url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{path}, unknown_status => '', critical_status => '', warning_status => ''); my $nodes; eval { @@ -174,7 +173,7 @@ sub internal_api_list_containers { my ($self, %options) = @_; my $response = $self->{http}->{$options{node_name}}->request( - url_path => '/api/' . $self->{option_results}->{api_version} . '/containers/docker/', + url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{path}, unknown_status => '', critical_status => '', warning_status => ''); my $containers = []; my $containers_ids; @@ -192,7 +191,12 @@ sub internal_api_list_containers { url_path => '/api/' . $self->{option_results}->{api_version} . '/containers/' . $container->{name} ) ); - push @$containers, {id => $json_response->{id}, names => $json_response->{aliases}, node => $options{node_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; @@ -222,7 +226,7 @@ sub internal_api_get_machine_stats { sub internal_api_get_container_stats { my ($self, %options) = @_; my $response = $self->{http}->{$options{node_name}}->request( - url_path => '/api/' . $self->{option_results}->{api_version} . '/containers/docker/' . $options{container_id}, + url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{path} . '/' . $options{container_id}, unknown_status => '', critical_status => '', warning_status => ''); my $container_stats; my $full_container_stats; @@ -278,8 +282,6 @@ sub api_list_nodes { num_cores => $info_node->{num_cores}, cpu_frequency_khz => $info_node->{cpu_frequency_khz}, memory_capacity => $info_node->{memory_capacity}, - #containers_stopped => $info_node->{ContainersStopped}, - #containers_paused => $info_node->{ContainersPaused}, }; foreach my $node (@{$list_nodes->{subcontainers}}) { push @{$nodes->{$node_name}->{nodes}}, { @@ -293,9 +295,6 @@ sub api_list_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->api_list_containers(); if (defined($options{container_id}) && $options{container_id} ne '') { @@ -330,11 +329,11 @@ __END__ =head1 NAME -Docker REST API +cadvisor REST API =head1 SYNOPSIS -Docker Rest API custom mode +CAdvisor Rest API custom mode =head1 REST API OPTIONS @@ -342,7 +341,7 @@ Docker Rest API custom mode =item B<--hostname> -IP Addr/FQDN of the docker node (can be multiple). +IP Addr/FQDN of the cadvisor node (can be multiple). =item B<--port> @@ -352,6 +351,10 @@ Port used (Default: 8080) Specify https if needed (Default: 'http') +=item B<--path> + +Path used (Default: '/containers/docker') + =item B<--credentials> Specify this option if you access webpage over basic authentification diff --git a/cloud/docker/cadvisor/mode/containerusage.pm b/cloud/cadvisor/restapi/mode/containerusage.pm similarity index 98% rename from cloud/docker/cadvisor/mode/containerusage.pm rename to cloud/cadvisor/restapi/mode/containerusage.pm index c363aae8b..8882cc8d2 100644 --- a/cloud/docker/cadvisor/mode/containerusage.pm +++ b/cloud/cadvisor/restapi/mode/containerusage.pm @@ -1,5 +1,5 @@ # -# Copyright 2018 Centreon (http://www.centreon.com/) +# 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 @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::cadvisor::mode::containerusage; +package cloud::cadvisor::restapi::mode::containerusage; use base qw(centreon::plugins::templates::counter); @@ -271,7 +271,7 @@ Exact container name (if multiple names: names separated by ':'). =item B<--use-name> -Use docker name for perfdata and display. +Use name for perfdata and display. =item B<--filter-name> diff --git a/cloud/docker/cadvisor/mode/diskio.pm b/cloud/cadvisor/restapi/mode/diskio.pm similarity index 84% rename from cloud/docker/cadvisor/mode/diskio.pm rename to cloud/cadvisor/restapi/mode/diskio.pm index 0e460712b..f07619e96 100644 --- a/cloud/docker/cadvisor/mode/diskio.pm +++ b/cloud/cadvisor/restapi/mode/diskio.pm @@ -1,5 +1,5 @@ # -# Copyright 2018 Centreon (http://www.centreon.com/) +# 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 @@ -18,17 +18,14 @@ # limitations under the License. # -package cloud::docker::cadvisor::mode::diskio; +package cloud::cadvisor::restapi::mode::diskio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; -use Digest::MD5 qw(md5_hex); use DateTime; -my $instance_mode; - sub set_counters { my ($self, %options) = @_; @@ -72,36 +69,16 @@ sub new { "container-name:s" => { name => 'container_name' }, "filter-name:s" => { name => 'filter_name' }, "use-name" => { name => 'use_name' }, - "warning-container-status:s" => { name => 'warning_container_status', default => '' }, - "critical-container-status:s" => { name => 'critical_container_status', default => '' }, }); return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $instance_mode = $self; - $self->change_macros(); -} - sub prefix_containers_diskio_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) = @_; @@ -114,12 +91,14 @@ sub manage_selection { 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}; @@ -195,7 +174,7 @@ __END__ =head1 MODE -Check container usage. +Check container disk io. =over 8 @@ -209,7 +188,7 @@ Exact container name (if multiple names: names separated by ':'). =item B<--use-name> -Use docker name for perfdata and display. +Use name for perfdata and display. =item B<--filter-name> @@ -218,29 +197,17 @@ 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$' +Example: --filter-counters='^diskio-read$' =item B<--warning-*> Threshold warning. -Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', -'cpu' (%), 'memory' (%). +Can be: 'diskio-read', 'diskio-write'. =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}. +Can be: 'diskio-read', 'diskio-write'. =back diff --git a/cloud/docker/cadvisor/mode/listcontainers.pm b/cloud/cadvisor/restapi/mode/listcontainers.pm similarity index 95% rename from cloud/docker/cadvisor/mode/listcontainers.pm rename to cloud/cadvisor/restapi/mode/listcontainers.pm index 833122ba4..27f01caeb 100644 --- a/cloud/docker/cadvisor/mode/listcontainers.pm +++ b/cloud/cadvisor/restapi/mode/listcontainers.pm @@ -1,5 +1,5 @@ # -# Copyright 2018 Centreon (http://www.centreon.com/) +# 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 @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::cadvisor::mode::listcontainers; +package cloud::cadvisor::restapi::mode::listcontainers; use base qw(centreon::plugins::mode); diff --git a/cloud/docker/cadvisor/mode/nodestatus.pm b/cloud/cadvisor/restapi/mode/nodestatus.pm similarity index 62% rename from cloud/docker/cadvisor/mode/nodestatus.pm rename to cloud/cadvisor/restapi/mode/nodestatus.pm index ae0c5b1f2..30961a53a 100644 --- a/cloud/docker/cadvisor/mode/nodestatus.pm +++ b/cloud/cadvisor/restapi/mode/nodestatus.pm @@ -18,62 +18,18 @@ # limitations under the License. # -package cloud::docker::cadvisor::mode::nodestatus; +package cloud::cadvisor::restapi::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; -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_node_status}) && $instance_mode->{option_results}->{critical_node_status} ne '' && - eval "$instance_mode->{option_results}->{critical_node_status}") { - $status = 'critical'; - } elsif (defined($instance_mode->{option_results}->{warning_node_status}) && $instance_mode->{option_results}->{warning_node_status} ne '' && - eval "$instance_mode->{option_results}->{warning_node_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} . ' [manager status: ' . $self->{result_values}->{manager_status} . ']'; - - return $msg; -} - -sub custom_status_calc { - my ($self, %options) = @_; - - $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; - $self->{result_values}->{manager_status} = $options{new_datas}->{$self->{instance} . '_manager_status'}; - $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 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} = [ @@ -134,42 +90,21 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { - "warning-node-status:s" => { name => 'warning_node_status', default => '' }, - "critical-node-status:s" => { name => 'critical_node_status', default => '%{status} !~ /ready/ || %{manager_status} !~ /reachable|-/' }, }); return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $instance_mode = $self; - $self->change_macros(); -} - sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } -sub change_macros { - my ($self, %options) = @_; - - foreach (('warning_node_status', 'critical_node_status')) { - if (defined($self->{option_results}->{$_})) { - $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; - } - } -} - sub manage_selection { my ($self, %options) = @_; $self->{node} = {}; - $self->{nodes} = {}; my $result = $options{custom}->api_list_nodes(); foreach my $node_name (keys %{$result}) { $self->{node}->{$node_name} = { @@ -197,25 +132,15 @@ 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'. +Can be: 'containers-running', 'num-cores', 'memory-capacity', 'cpu-frequency'. =item B<--critical-*> Threshold critical. -Can be: 'containers-running', 'containers-paused', 'containers-stopped'., +Can be: 'containers-running', 'num-cores', 'memory-capacity', 'cpu-frequency'. =back diff --git a/cloud/docker/cadvisor/mode/traffic.pm b/cloud/cadvisor/restapi/mode/traffic.pm similarity index 75% rename from cloud/docker/cadvisor/mode/traffic.pm rename to cloud/cadvisor/restapi/mode/traffic.pm index 8565d37fe..f05b3c9c4 100644 --- a/cloud/docker/cadvisor/mode/traffic.pm +++ b/cloud/cadvisor/restapi/mode/traffic.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::cadvisor::mode::traffic; +package cloud::cadvisor::restapi::mode::traffic; use base qw(centreon::plugins::templates::counter); @@ -72,37 +72,17 @@ sub new { "container-name:s" => { name => 'container_name' }, "filter-name:s" => { name => 'filter_name' }, "use-name" => { name => 'use_name' }, - "warning-container-status:s" => { name => 'warning_container_status', default => '' }, - "critical-container-status:s" => { name => 'critical_container_status', default => '' }, }); return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $instance_mode = $self; - $self->change_macros(); -} - sub prefix_containers_traffic_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) = @_; @@ -123,6 +103,7 @@ sub manage_selection { $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}; @@ -135,19 +116,26 @@ sub manage_selection { 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, - }; - foreach my $interface_index (0..(scalar(@{$first_stat->{network}->{interfaces}}) - 1)) { - my $name = defined($self->{option_results}->{use_name}) ? $name : $container_id; - $name .= '.' . $first_stat->{network}->{interfaces}->[$interface_index]->{name}; + }; + + my $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, - 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, + 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, }; } } @@ -182,7 +170,7 @@ __END__ =head1 MODE -Check container usage. +Check container traffic usage. =over 8 @@ -205,29 +193,17 @@ 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$' +Example: --filter-counters='^traffic-in$' =item B<--warning-*> Threshold warning. -Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', -'cpu' (%), 'memory' (%). +Can be: 'traffic-in', 'traffic-out'. =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}. +Can be: 'traffic-in', 'traffic-out'. =back diff --git a/cloud/docker/cadvisor/plugin.pm b/cloud/cadvisor/restapi/plugin.pm similarity index 63% rename from cloud/docker/cadvisor/plugin.pm rename to cloud/cadvisor/restapi/plugin.pm index 0bd785e1b..ef65a54d1 100644 --- a/cloud/docker/cadvisor/plugin.pm +++ b/cloud/cadvisor/restapi/plugin.pm @@ -1,5 +1,5 @@ # -# Copyright 2018 Centreon (http://www.centreon.com/) +# 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 @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::docker::cadvisor::plugin; +package cloud::cadvisor::restapi::plugin; use strict; use warnings; @@ -31,14 +31,14 @@ sub new { $self->{version} = '0.3'; %{$self->{modes}} = ( - 'container-usage' => 'cloud::docker::cadvisor::mode::containerusage', - 'disk-io' => 'cloud::docker::cadvisor::mode::diskio', - 'traffic' => 'cloud::docker::cadvisor::mode::traffic', - 'list-containers' => 'cloud::docker::cadvisor::mode::listcontainers', - 'node-status' => 'cloud::docker::cadvisor::mode::nodestatus', + '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::docker::cadvisor::custom::api'; + $self->{custom_modes}{api} = 'cloud::cadvisor::restapi::custom::api'; return $self; } @@ -48,14 +48,13 @@ sub init { $self->SUPER::init(%options); } - 1; __END__ =head1 PLUGIN DESCRIPTION -Check Docker nodes and containers through cAdvisor API. +Check nodes and containers through cAdvisor API. Requirements: cAdvisor supporting API version 1.3+ =cut