enhance cisco vcs

This commit is contained in:
garnier-quentin 2020-09-25 14:44:30 +02:00
parent c5ae64541d
commit 50ce0c5811
5 changed files with 338 additions and 388 deletions

View File

@ -23,7 +23,7 @@ package network::cisco::vcs::restapi::custom::xmlapi;
use strict; use strict;
use warnings; use warnings;
use centreon::plugins::http; use centreon::plugins::http;
use XML::Simple; use XML::LibXML::Simple;
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
@ -41,13 +41,15 @@ sub new {
if (!defined($options{noptions})) { if (!defined($options{noptions})) {
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
'hostname:s' => { name => 'hostname' }, 'hostname:s' => { name => 'hostname' },
'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' },
'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' },
'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' },
'username:s' => { name => 'username' }, 'api-password:s' => { name => 'api_password' },
'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' },
'timeout:s' => { name => 'timeout' } 'unknown-http-status:s' => { name => 'unknown_http_status' },
'warning-http-status:s' => { name => 'warning_http_status' },
'critical-http-status:s' => { name => 'critical_http_status' }
}); });
} }
$options{options}->add_help(package => __PACKAGE__, sections => 'XMLAPI OPTIONS', once => 1); $options{options}->add_help(package => __PACKAGE__, sections => 'XMLAPI OPTIONS', once => 1);
@ -69,24 +71,26 @@ sub set_defaults {}
sub check_options { sub check_options {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : '';
$self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443;
$self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https';
$self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : '';
$self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : '';
$self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/getxml?location='; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 20;
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300';
$self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : '';
$self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : '';
if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { if ($self->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option.");
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
if (!defined($self->{option_results}->{username}) || $self->{option_results}->{username} eq '') { if ($self->{api_username} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --username option."); $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option.");
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { if ($self->{api_password} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --password option."); $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option.");
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
@ -100,28 +104,19 @@ sub build_options_for_httplib {
$self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{timeout} = $self->{timeout};
$self->{option_results}->{port} = $self->{port}; $self->{option_results}->{port} = $self->{port};
$self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{proto} = $self->{proto};
$self->{option_results}->{username} = $self->{username}; $self->{option_results}->{username} = $self->{api_username};
$self->{option_results}->{password} = $self->{password}; $self->{option_results}->{password} = $self->{api_password};
$self->{option_results}->{credentials} = 1; $self->{option_results}->{credentials} = 1;
$self->{option_results}->{basic} = 1; $self->{option_results}->{basic} = 1;
$self->{option_results}->{warning_status} = '';
$self->{option_results}->{critical_status} = '';
} }
sub settings { sub settings {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->build_options_for_httplib(); $self->build_options_for_httplib();
$self->{http}->set_options(%{$self->{option_results}}); $self->{http}->set_options(%{$self->{option_results}});
} }
sub get_connection_info {
my ($self, %options) = @_;
return $self->{hostname} . ":" . $self->{port};
}
sub get_hostname { sub get_hostname {
my ($self, %options) = @_; my ($self, %options) = @_;
@ -137,21 +132,23 @@ sub get_port {
sub get_endpoint { sub get_endpoint {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->settings; $self->settings();
my $content = $self->{http}->request(
my $content = $self->{http}->request(url_path => $self->{url_path} . $options{method}); url_path => $options{endpoint},
unknown_status => $self->{unknown_http_status},
warning_status => $self->{warning_http_status},
critical_status => $self->{critical_http_status}
);
my $xml_result; my $xml_result;
eval { eval {
$xml_result = XMLin($content, ForceArray => ['Call', 'Zone'], KeyAttr => []); $xml_result = XMLin($content, ForceArray => $options{force_array}, KeyAttr => []);
}; };
if ($@) { if ($@) {
$self->{output}->output_add(long_msg => $content, debug => 1);
$self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@");
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
if (defined($xml_result->{XPathError})) { if (defined($xml_result->{XPathError})) {
$self->{output}->output_add(long_msg => $content, debug => 1);
$self->{output}->add_option_msg(short_msg => "Api return error: " . $xml_result->{XPathError}->{Reason}); $self->{output}->add_option_msg(short_msg => "Api return error: " . $xml_result->{XPathError}->{Reason});
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
@ -179,10 +176,6 @@ Cisco VCS XML API
API hostname. API hostname.
=item B<--url-path>
API url path (Default: '/getxml?location=')
=item B<--port> =item B<--port>
API port (Default: 443) API port (Default: 443)
@ -191,11 +184,11 @@ API port (Default: 443)
Specify https if needed (Default: 'https') Specify https if needed (Default: 'https')
=item B<--username> =item B<--api-username>
Set API username Set API username
=item B<--password> =item B<--api-password>
Set API password Set API password

View File

@ -24,158 +24,140 @@ use base qw(centreon::plugins::templates::counter);
use strict; use strict;
use warnings; use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Date::Parse;
use Digest::MD5 qw(md5_hex);
sub custom_status_output { sub prefix_global_output {
my ($self, %options) = @_; my ($self, %options) = @_;
my $msg = sprintf("state is '%s' [Duration: %s s]", return 'Calls ';
$self->{result_values}->{state}, $self->{result_values}->{duration});
return $msg;
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{serial_number} = $options{new_datas}->{$self->{instance} . '_SerialNumber'};
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_State'};
$self->{result_values}->{duration} = $options{new_datas}->{$self->{instance} . '_Duration'};
return 0;
} }
sub set_counters { sub set_counters {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->{maps_counters_type} = [ $self->{maps_counters_type} = [
{ name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }
{ name => 'calls', type => 1, cb_prefix_output => 'prefix_call_output', message_multiple => 'All calls are ok' },
]; ];
$self->{maps_counters}->{global} = [ $self->{maps_counters}->{global} = [
{ label => 'traversal', set => { { label => 'dummy', threshold => 0, display_ok => 0, set => {
key_values => [ { name => 'Traversal' } ], key_values => [ { name => 'last_cdr_start_time' } ],
output_template => 'Traversal: %d', output_template => 'none',
perfdatas => [ perfdatas => []
{ label => 'traversal', value => 'Traversal', template => '%d',
min => 0, unit => 'calls' },
],
} }
}, }
{ label => 'non-traversal', set => {
key_values => [ { name => 'NonTraversal' } ],
output_template => 'Non Traversal: %d',
perfdatas => [
{ label => 'non_traversal', value => 'NonTraversal', template => '%d',
min => 0, unit => 'calls' },
],
}
},
{ label => 'collaboration-edge', set => {
key_values => [ { name => 'CollaborationEdge' } ],
output_template => 'Collaboration Edge: %d',
perfdatas => [
{ label => 'collaboration_edge', value => 'CollaborationEdge', template => '%d',
min => 0, unit => 'calls' },
],
}
},
{ label => 'cloud', set => {
key_values => [ { name => 'Cloud' } ],
output_template => 'Cloud: %d',
perfdatas => [
{ label => 'cloud', value => 'Cloud', template => '%d',
min => 0, unit => 'calls' },
],
}
},
{ label => 'microsoft-content', set => {
key_values => [ { name => 'MicrosoftContent' } ],
output_template => 'Microsoft Content: %d',
perfdatas => [
{ label => 'microsoft_content', value => 'MicrosoftContent', template => '%d',
min => 0, unit => 'calls' },
],
}
},
{ label => 'microsoft-imp', set => {
key_values => [ { name => 'MicrosoftIMP' } ],
output_template => 'Microsoft IMP: %d',
perfdatas => [
{ label => 'microsoft_imp', value => 'MicrosoftIMP', template => '%d',
min => 0, unit => 'calls' },
],
}
},
]; ];
$self->{maps_counters}->{calls} = [
{ label => 'status', set => {
key_values => [ { name => 'State' }, { name => 'Duration' }, { name => 'SerialNumber' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold,
}
},
];
}
sub prefix_global_output { foreach ((
my ($self, %options) = @_; ['traversal', 1, 'traversal'], ['nontraversal', 1, 'non traversal'],
['cloud', 1, 'cloud'], ['collaborationedge', 0, 'collaboration edge'],
['microsoftcontent', 0, 'microsoft content'], ['microsoftimp', 0, 'microsoft imp']
)) {
push @{$self->{maps_counters}->{global}},
{
label => $_->[0] . '-current', nlabel => 'calls.' . $_->[0] . '.current.count', display_ok => $_->[1], set => {
key_values => [ { name => $_->[0] . '_current' } ],
output_template => $_->[2] . ' current: %d',
perfdatas => [
{ template => '%d', min => 0 }
]
}
},
{
label => $_->[0] . '-total', nlabel => 'calls.' . $_->[0] . '.total.count', display_ok => 0, set => {
key_values => [ { name => $_->[0] . '_total', diff => 1 } ],
output_template => $_->[2] . ' total: %d',
perfdatas => [
{ template => '%d', min => 0 }
]
}
};
}
return "Number of Calls "; foreach ((
} ['connectionfailed', 1, 'connection failed'], ['disconnected', 1, 'disconnected']
)) {
sub prefix_call_output { push @{$self->{maps_counters}->{global}}, {
my ($self, %options) = @_; label => $_->[0] . '-total', nlabel => 'calls.' . $_->[0] . '.total.count', display_ok => $_->[1], set => {
key_values => [ { name => $_->[0] } ],
return "Call '" . $options{instance_value}->{SerialNumber} . "' "; output_template => $_->[2] . ': %d',
perfdatas => [
{ template => '%d', min => 0 }
]
}
};
}
} }
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options); my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => $options{options}->add_options(arguments => {
{ });
"warning-status:s" => { name => 'warning_status' },
"critical-status:s" => { name => 'critical_status', default => '%{state} ne "Connected"' },
});
return $self; return $self;
} }
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection { sub manage_selection {
my ($self, %options) = @_; my ($self, %options) = @_;
my $usages = $options{custom}->get_endpoint(method => '/Status/ResourceUsage/Calls'); $self->{cache_name} = 'cisco_vcs_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'));
$self->{global}->{Traversal} = $usages->{ResourceUsage}->{Calls}->{Traversal}->{Current}->{content}; my $calls = $options{custom}->get_endpoint(
$self->{global}->{NonTraversal} = $usages->{ResourceUsage}->{Calls}->{NonTraversal}->{Current}->{content}; endpoint => '/getxml?location=/Status/ResourceUsage/Calls'
$self->{global}->{CollaborationEdge} = $usages->{ResourceUsage}->{Calls}->{CollaborationEdge}->{Current}->{content}; );
$self->{global}->{Cloud} = $usages->{ResourceUsage}->{Calls}->{Cloud}->{Current}->{content};
$self->{global}->{MicrosoftContent} = $usages->{ResourceUsage}->{Calls}->{MicrosoftContent}->{Current}->{content};
$self->{global}->{MicrosoftIMP} = $usages->{ResourceUsage}->{Calls}->{MicrosoftIMP}->{Current}->{content};
my $results = $options{custom}->get_endpoint(method => '/Status/Calls'); $self->{global} = {
traversal_current => $calls->{ResourceUsage}->{Calls}->{Traversal}->{Current}->{content},
traversal_total => $calls->{ResourceUsage}->{Calls}->{Traversal}->{Total}->{content},
nontraversal_current => $calls->{ResourceUsage}->{Calls}->{NonTraversal}->{Current}->{content},
nontraversal_total => $calls->{ResourceUsage}->{Calls}->{NonTraversal}->{Total}->{content},
cloud_current => $calls->{ResourceUsage}->{Calls}->{Cloud}->{Current}->{content},
cloud_total => $calls->{ResourceUsage}->{Calls}->{Cloud}->{Total}->{content},
collaborationedge_current => $calls->{ResourceUsage}->{Calls}->{CollaborationEdge}->{Current}->{content},
collaborationedge_total => $calls->{ResourceUsage}->{Calls}->{CollaborationEdge}->{Total}->{content},
microsoftcontent_current => $calls->{ResourceUsage}->{Calls}->{MicrosoftContent}->{Current}->{content},
microsoftcontent_total => $calls->{ResourceUsage}->{Calls}->{MicrosoftContent}->{Total}->{content},
microsoftimp_current => $calls->{ResourceUsage}->{Calls}->{MicrosoftIMP}->{Current}->{content},
microsoftimp_total => $calls->{ResourceUsage}->{Calls}->{MicrosoftIMP}->{Total}->{content},
connectionfailed => 0,
disconnected => 0
};
$self->{calls} = {}; my $last_cdr_start_time = $self->read_statefile_key(key => 'global_last_cdr_start_time');
$last_cdr_start_time = 0 if (!defined($last_cdr_start_time));
my $results = $options{custom}->get_endpoint(
endpoint => '/history.xml?location=/Calls',
force_array => ['Call']
);
#<StartTime item="1">2020-09-24 12:28:52.267179</StartTime>
my $max_start_time = $last_cdr_start_time;
foreach my $call (@{$results->{Calls}->{Call}}) { foreach my $call (@{$results->{Calls}->{Call}}) {
next if (!defined($call->{SerialNumber})); my $tmp_time = Date::Parse::str2time($call->{StartTime}->{content});
$self->{calls}->{$call->{SerialNumber}->{content}} = { if (!defined($tmp_time)) {
SerialNumber => $call->{SerialNumber}->{content}, $self->{output}->output_add(
Duration => $call->{Duration}->{content}, severity => 'UNKNOWN',
State => $call->{State}->{content}, short_msg => "can't parse date '" . $call->{StartTime}->{content} . "'"
}; );
next;
}
$tmp_time = int($tmp_time * 10000);
$max_start_time = $tmp_time if ($max_start_time < $tmp_time);
if ($tmp_time > $last_cdr_start_time) {
$call->{State}->{content} =~ s/\s+//g;
$self->{global}->{ lc($call->{State}->{content}) }++
if (defined($self->{global}->{ lc($call->{State}->{content}) }));
}
} }
$self->{global}->{last_cdr_start_time} = $max_start_time;
} }
1; 1;
@ -184,31 +166,20 @@ __END__
=head1 MODE =head1 MODE
Check calls count and state. Check current calls and history.
=over 8 =over 8
=item B<--warning-*> =item B<--warning-*> B<--critical-*>
Threshold warning. Thresholds.
Can be: 'traversal', 'non-traversal', 'collaboration-edge', Can be: 'traversal-current', 'traversal-total',
'cloud', 'microsoft-content', 'microsoft-imp'. 'nontraversal-current', 'nontraversal-total',
'cloud-current', 'cloud-total', '
=item B<--critical-*> 'collaborationedge-current', 'collaborationedge-total',
'microsoftcontent-current', 'microsoftcontent-total',
Threshold critical. 'microsoftimp-current', 'microsoftimp-total',
Can be: 'traversal', 'non-traversal', 'collaboration-edge', 'connectionfailed-total', 'disconnected-total'.
'cloud', 'microsoft-content', 'microsoft-imp'.
=item B<--warning-status>
Set warning threshold for status. (Default: '').
Can use special variables like: %{state}, %{serial_number}, %{duration}.
=item B<--critical-status>
Set critical threshold for status. (Default: '%{state} ne "Connected"').
Can use special variables like: %{state}, %{serial_number}, %{duration}.
=back =back

View File

@ -25,20 +25,33 @@ use base qw(centreon::plugins::templates::counter);
use strict; use strict;
use warnings; use warnings;
use Digest::MD5 qw(md5_hex); use Digest::MD5 qw(md5_hex);
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
sub custom_status_output { sub custom_status_output {
my ($self, %options) = @_; my ($self, %options) = @_;
my $msg = sprintf("Status is '%s'", $self->{result_values}->{status}); return sprintf(
return $msg; "http proxy status is '%s'",
$self->{result_values}->{status}
);
} }
sub custom_status_calc { sub prefix_connections_output {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_Status'}; return 'Connections ';
return 0; }
sub prefix_requests_output {
my ($self, %options) = @_;
return 'Resquests ';
}
sub prefix_responses_output {
my ($self, %options) = @_;
return 'Responses ';
} }
sub set_counters { sub set_counters {
@ -48,170 +61,150 @@ sub set_counters {
{ name => 'global', type => 0 }, { name => 'global', type => 0 },
{ name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' }, { name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' },
{ name => 'requests', type => 0, cb_prefix_output => 'prefix_requests_output' }, { name => 'requests', type => 0, cb_prefix_output => 'prefix_requests_output' },
{ name => 'responses', type => 0, cb_prefix_output => 'prefix_responses_output' }, { name => 'responses', type => 0, cb_prefix_output => 'prefix_responses_output' }
]; ];
$self->{maps_counters}->{global} = [ $self->{maps_counters}->{global} = [
{ label => 'status', set => { { label => 'status', type => 2, critical_default => '%{status} ne "Active"',set => {
key_values => [ { name => 'Status' } ], key_values => [ { name => 'status' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'), closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; }, closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold, closure_custom_threshold_check => \&catalog_status_threshold_ng
} }
}, }
]; ];
$self->{maps_counters}->{connections} = [ $self->{maps_counters}->{connections} = [
{ label => 'client-connections', set => { { label => 'connections-client', nlabel => 'httproxy.connections.client.persecond', set => {
key_values => [ { name => 'TotalClientConnection', per_second => 1 } ], key_values => [ { name => 'total_client_connection', per_second => 1 } ],
output_template => 'Client: %.2f/s', output_template => 'client: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'client_connections', template => '%.2f', min => 0, unit => 'connections/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'server-connections', set => { { label => 'connections-server', nlabel => 'httproxy.connections.server.persecond', set => {
key_values => [ { name => 'TotalServerConnection', per_second => 1 } ], key_values => [ { name => 'total_server_connection', per_second => 1 } ],
output_template => 'Server: %.2f/s', output_template => 'server: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'server_connections', template => '%.2f', min => 0, unit => 'connections/s' }, { template => '%.2f', min => 0 }
], ]
} }
} }
]; ];
$self->{maps_counters}->{requests} = [ $self->{maps_counters}->{requests} = [
{ label => 'completed-requests', set => { { label => 'requests-completed', nlabel => 'httproxy.requests.completed.persecond', set => {
key_values => [ { name => 'CompletedRequests', per_second => 1 } ], key_values => [ { name => 'completed', per_second => 1 } ],
output_template => 'Completed: %.2f/s', output_template => 'completed: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'completed_requests', template => '%.2f', min => 0, unit => 'requests/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'get-requests', set => { { label => 'requests-get', nlabel => 'httproxy.requests.get.persecond', set => {
key_values => [ { name => 'GetRequests', per_second => 1 } ], key_values => [ { name => 'get', per_second => 1 } ],
output_template => 'Get: %.2f/s', output_template => 'get: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'get_requests', template => '%.2f', min => 0, unit => 'requests/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'post-requests', set => { { label => 'requests-post', nlabel => 'httproxy.requests.post.persecond', set => {
key_values => [ { name => 'PostRequests', per_second => 1 } ], key_values => [ { name => 'post', per_second => 1 } ],
output_template => 'Post: %.2f/s', output_template => 'post: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'post_requests', template => '%.2f', min => 0, unit => 'requests/s' }, { template => '%.2f', min => 0 }
], ]
} }
} }
]; ];
$self->{maps_counters}->{responses} = [ $self->{maps_counters}->{responses} = [
{ label => 'responses-1xx', set => { { label => 'responses-1xx', nlabel => 'httproxy.responses.1xx.persecond', set => {
key_values => [ { name => 'Response1XXCount', per_second => 1 } ], key_values => [ { name => 'response1xxx', per_second => 1 } ],
output_template => '1XX: %.2f/s', output_template => '1xx: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'responses_1xx', template => '%.2f', min => 0, unit => 'responses/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'responses-2xx', set => { { label => 'responses-2xx', nlabel => 'httproxy.responses.2xx.persecond', set => {
key_values => [ { name => 'Response2XXCount', per_second => 1 } ], key_values => [ { name => 'response2xxx', per_second => 1 } ],
output_template => '2XX: %.2f/s', output_template => '2xx: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'responses_2xx', template => '%.2f', min => 0, unit => 'responses/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'responses-3xx', set => { { label => 'responses-3xx', nlabel => 'httproxy.responses.3xx.persecond', set => {
key_values => [ { name => 'Response3XXCount', per_second => 1 } ], key_values => [ { name => 'response3xxx', per_second => 1 } ],
output_template => '3XX: %.2f/s', output_template => '3xx: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'responses_3xx', template => '%.2f', min => 0, unit => 'responses/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'responses-4xx', set => { { label => 'responses-4xx', nlabel => 'httproxy.responses.4xx.persecond', set => {
key_values => [ { name => 'Response4XXCount', per_second => 1 } ], key_values => [ { name => 'response4xxx', per_second => 1 } ],
output_template => '4XX: %.2f/s', output_template => '4xx: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'responses_4xx', template => '%.2f', min => 0, unit => 'responses/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'responses-5xx', set => { { label => 'responses-5xx', nlabel => 'httproxy.responses.5xx.persecond', set => {
key_values => [ { name => 'Response5XXCount', per_second => 1 } ], key_values => [ { name => 'response5xxx', per_second => 1 } ],
output_template => '5XX: %.2f/s', output_template => '5xx: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'responses_5xx', template => '%.2f', min => 0, unit => 'responses/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, }
]; ];
} }
sub prefix_connections_output {
my ($self, %options) = @_;
return "Connections ";
}
sub prefix_requests_output {
my ($self, %options) = @_;
return "Resquests ";
}
sub prefix_responses_output {
my ($self, %options) = @_;
return "Responses ";
}
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
'warning-status:s' => { name => 'warning_status' },
'critical-status:s' => { name => 'critical_status', default => '%{status} ne "Active"' }
}); });
return $self; return $self;
} }
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection { sub manage_selection {
my ($self, %options) = @_; my ($self, %options) = @_;
my $results = $options{custom}->get_endpoint(method => '/Status/HTTPProxy'); my $results = $options{custom}->get_endpoint(
endpoint => '/getxml?location=/Status/HTTPProxy'
);
$self->{global} = {}; $self->{global} = {
$self->{connections} = {}; status => $results->{HTTPProxy}->{Status}->{content}
$self->{requests} = {}; };
$self->{responses} = {}; if (defined($results->{HTTPProxy}->{Stats})) {
$self->{connections} = {
total_client_connection => $results->{HTTPProxy}->{Stats}->{TotalClientConnection}->{content},
total_server_connection => $results->{HTTPProxy}->{Stats}->{TotalServerConnection}->{content}
};
$self->{requests} = {
completed => $results->{HTTPProxy}->{Stats}->{CompletedRequests}->{content},
get => $results->{HTTPProxy}->{Stats}->{GetRequests}->{content},
post => $results->{HTTPProxy}->{Stats}->{PostRequests}->{content}
};
$self->{responses} = {
response1xxx => $results->{HTTPProxy}->{Stats}->{Response1XXCount}->{content},
response2xxx => $results->{HTTPProxy}->{Stats}->{Response2XXCount}->{content},
response3xxx => $results->{HTTPProxy}->{Stats}->{Response3XXCount}->{content},
response4xxx => $results->{HTTPProxy}->{Stats}->{Response4XXCount}->{content},
response5xxx => $results->{HTTPProxy}->{Stats}->{Response5XXCount}->{content}
};
}
$self->{global}->{Status} = $results->{HTTPProxy}->{Status}->{content}; $self->{cache_name} = 'cisco_vcs_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' .
$self->{connections}->{TotalClientConnection} = $results->{HTTPProxy}->{Stats}->{TotalClientConnection}->{content};
$self->{connections}->{TotalServerConnection} = $results->{HTTPProxy}->{Stats}->{TotalServerConnection}->{content};
$self->{requests}->{CompletedRequests} = $results->{HTTPProxy}->{Stats}->{CompletedRequests}->{content};
$self->{requests}->{GetRequests} = $results->{HTTPProxy}->{Stats}->{GetRequests}->{content};
$self->{requests}->{PostRequests} = $results->{HTTPProxy}->{Stats}->{PostRequests}->{content};
$self->{responses}->{Response1XXCount} = $results->{HTTPProxy}->{Stats}->{Response1XXCount}->{content};
$self->{responses}->{Response2XXCount} = $results->{HTTPProxy}->{Stats}->{Response2XXCount}->{content};
$self->{responses}->{Response3XXCount} = $results->{HTTPProxy}->{Stats}->{Response3XXCount}->{content};
$self->{responses}->{Response4XXCount} = $results->{HTTPProxy}->{Stats}->{Response4XXCount}->{content};
$self->{responses}->{Response5XXCount} = $results->{HTTPProxy}->{Stats}->{Response5XXCount}->{content};
$self->{cache_name} = "cisco_vcs_" . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'));
} }
@ -230,28 +223,21 @@ Check HTTP proxy status and statistics.
Only display some counters (regexp can be used). Only display some counters (regexp can be used).
(Example: --filter-counters='responses') (Example: --filter-counters='responses')
=item B<--warning-*> =item B<--warning-*> B<--critical-*>
Threshold warning (/s). Threshold.
Can be: 'client-connections', 'server-connections', 'completed-requests', Can be: 'connections-client', 'connections-server',
'get-requests', 'post-requests', 'responses-1xx', 'responses-2xx', 'requests-completed', 'requests-get', 'requests-post',
'responses-3xx', 'responses-4xx', 'responses-5xx'. 'responses-1xx', 'responses-2xx', 'responses-3xx', 'responses-4xx', 'responses-5xx'.
=item B<--critical-*>
Threshold critical (/s).
Can be: 'client-connections', 'server-connections', 'completed-requests',
'get-requests', 'post-requests', 'responses-1xx', 'responses-2xx',
'responses-3xx', 'responses-4xx', 'responses-5xx'.
=item B<--warning-status> =item B<--warning-status>
Set warning threshold for status. (Default: ''). Set warning threshold for status.
Can use special variables like: %{status}. Can use special variables like: %{status}.
=item B<--critical-status> =item B<--critical-status>
Set critical threshold for status. (Default: '%{status} ne "Active"'). Set critical threshold for status (Default: '%{status} ne "Active"').
Can use special variables like: %{status}. Can use special variables like: %{status}.
=back =back

View File

@ -25,14 +25,15 @@ use base qw(centreon::plugins::templates::counter);
use strict; use strict;
use warnings; use warnings;
use Digest::MD5 qw(md5_hex); use Digest::MD5 qw(md5_hex);
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
sub custom_status_output { sub custom_status_output {
my ($self, %options) = @_; my ($self, %options) = @_;
my $msg = sprintf("Status is '%s' [Type: %s]", return sprintf(
$self->{result_values}->{status}, $self->{result_values}->{type}); "status is '%s' [type: %s]",
return $msg; $self->{result_values}->{status}, $self->{result_values}->{type}
);
} }
sub custom_status_calc { sub custom_status_calc {
@ -44,142 +45,143 @@ sub custom_status_calc {
return 0; return 0;
} }
sub prefix_searches_output {
my ($self, %options) = @_;
return 'Searches ';
}
sub prefix_zones_output {
my ($self, %options) = @_;
return "Zone '" . $options{instance_value}->{name} . "' ";
}
sub set_counters { sub set_counters {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->{maps_counters_type} = [ $self->{maps_counters_type} = [
{ name => 'global', type => 0}, { name => 'global', type => 0},
{ name => 'searches', type => 0, cb_prefix_output => 'prefix_searches_output' }, { name => 'searches', type => 0, cb_prefix_output => 'prefix_searches_output' },
{ name => 'zones', type => 1, cb_prefix_output => 'prefix_zones_output', message_multiple => 'All zones are ok' }, { name => 'zones', type => 1, cb_prefix_output => 'prefix_zones_output', message_multiple => 'All zones are ok' }
]; ];
$self->{maps_counters}->{global} = [ $self->{maps_counters}->{global} = [
{ label => 'zones-count', set => { { label => 'zones-count', nlabel => 'zones.total.count', set => {
key_values => [ { name => 'count' } ], key_values => [ { name => 'count' } ],
output_template => 'Number of zones: %d', output_template => 'Number of zones: %d',
perfdatas => [ perfdatas => [
{ label => 'zones_count', template => '%d', min => 0 } { template => '%d', min => 0 }
] ]
} }
} }
]; ];
$self->{maps_counters}->{searches} = [ $self->{maps_counters}->{searches} = [
{ label => 'searches-total', set => { { label => 'searches-total', nlabel => 'zones.searches.total.persecond', set => {
key_values => [ { name => 'Total', per_second => 1 } ], key_values => [ { name => 'total', per_second => 1 } ],
output_template => 'Total: %.2f/s', output_template => 'total: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'searches_total', template => '%.2f', min => 0, unit => 'searches/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'searches-dropped', set => { { label => 'searches-dropped', nlabel => 'zones.searches.dropped.persecond', set => {
key_values => [ { name => 'Dropped', per_second => 1 } ], key_values => [ { name => 'dropped', per_second => 1 } ],
output_template => 'Dropped: %.2f/s', output_template => 'dropped: %.2f/s',
perfdatas => [ perfdatas => [
{ label => 'searches_dropped', template => '%.2f', min => 0, unit => 'searches/s' }, { template => '%.2f', min => 0 }
], ]
} }
}, },
{ label => 'searches-max-sub-search-exceeded', set => { { label => 'searches-maxsub-exceeded', nlabel => 'zones.searches.maxsub.exceeded.count', set => {
key_values => [ { name => 'MaxSubSearchExceeded', per_second => 1 } ], key_values => [ { name => 'max_sub_search_exceeded', diff => 1 } ],
output_template => 'Max Sub Search Exceeded: %.2f/s', output_template => 'max sub exceeded: %s',
perfdatas => [ perfdatas => [
{ label => 'searches_max_sub_search_exceeded', template => '%.2f', { template => '%.2f', min => 0 }
min => 0, unit => 'searches/s' }, ]
],
} }
}, },
{ label => 'searches-max-targets-exceeded', set => { { label => 'searches-maxtargets-exceeded', nlabel => 'zones.searches.maxtargets.exceeded.count', set => {
key_values => [ { name => 'MaxTargetsExceeded', per_second => 1 } ], key_values => [ { name => 'max_targets_exceeded', diff => 1 } ],
output_template => 'Max Targets Exceeded: %.2f/s', output_template => 'max targets exceeded: %s',
perfdatas => [ perfdatas => [
{ label => 'searches_max_targets_exceeded', template => '%.2f', min => 0, unit => 'searches/s' }, { template => '%s', min => 0 }
], ]
} }
} }
]; ];
$self->{maps_counters}->{zones} = [ $self->{maps_counters}->{zones} = [
{ label => 'status', set => { { label => 'status', type => 2, critical_default => '%{status} ne "Active"', set => {
key_values => [ { name => 'Status' }, { name => 'Type' }, { name => 'Name' } ], key_values => [ { name => 'status' }, { name => 'type' }, { name => 'name' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'), closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; }, closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold closure_custom_threshold_check => \&catalog_status_threshold_ng
} }
}, },
{ label => 'calls-count', set => { { label => 'zone-calls-current', nlabel => 'zone.calls.current.count', set => {
key_values => [ { name => 'Calls' }, { name => 'Name' } ], key_values => [ { name => 'calls' } ],
output_template => 'Number of Calls: %d', output_template => 'current calls: %d',
perfdatas => [ perfdatas => [
{ label => 'calls_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'Name' } { template => '%d', min => 0, label_extra_instance => 1 }
] ]
} }
} }
]; ];
} }
sub prefix_searches_output {
my ($self, %options) = @_;
return "Searches ";
}
sub prefix_zones_output {
my ($self, %options) = @_;
return "Zone '" . $options{instance_value}->{Name} . "' ";
}
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
'warning-status:s' => { name => 'warning_status' }, 'filter-zone-name:s' => { name => 'filter_zone_name' }
'critical-status:s' => { name => 'critical_status', default => '%{status} ne "Active"' }
}); });
return $self; return $self;
} }
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection { sub manage_selection {
my ($self, %options) = @_; my ($self, %options) = @_;
my $results = $options{custom}->get_endpoint(method => '/Status/Zones'); my $results = $options{custom}->get_endpoint(
endpoint => '/getxml?location=/Status/Zones',
force_array => ['Zone', 'Call']
);
$self->{global}->{count} = 0; $self->{global}->{count} = 0;
$self->{searches} = {}; $self->{searches} = {
total => $results->{Zones}->{Searches}->{Total}->{content},
dropped => $results->{Zones}->{Searches}->{Dropped}->{content},
max_sub_search_exceeded => $results->{Zones}->{Searches}->{MaxSubSearchExceeded}->{content},
max_targets_exceeded => $results->{Zones}->{Searches}->{MaxTargetsExceeded}->{content}
};
$self->{zones} = {}; $self->{zones} = {};
$self->{searches}->{Total} = $results->{Zones}->{Searches}->{Total}->{content};
$self->{searches}->{Dropped} = $results->{Zones}->{Searches}->{Dropped}->{content};
$self->{searches}->{MaxSubSearchExceeded} = $results->{Zones}->{Searches}->{MaxSubSearchExceeded}->{content};
$self->{searches}->{MaxTargetsExceeded} = $results->{Zones}->{Searches}->{MaxTargetsExceeded}->{content};
foreach my $zone (@{$results->{Zones}->{Zone}}) { foreach my $zone (@{$results->{Zones}->{Zone}}) {
next if (!defined($zone->{Name})); next if (!defined($zone->{Name}));
$self->{zones}->{$zone->{Name}->{content}} = {
Type => $zone->{Type}->{content}, if (defined($self->{option_results}->{filter_zone_name}) && $self->{option_results}->{filter_zone_name} ne '' &&
Name => $zone->{Name}->{content}, $zone->{Name}->{content} !~ /$self->{option_results}->{filter_zone_name}/) {
Calls => (defined($zone->{Calls})) ? scalar(@{$zone->{Calls}->{Call}}) : 0, $self->{output}->output_add(long_msg => "skipping '" . $zone->{Name}->{content} . "': no matching filter vserver.", debug => 1);
Status => $zone->{Status}->{content}, next;
}
$self->{zones}->{ $zone->{Name}->{content} } = {
type => $zone->{Type}->{content},
name => $zone->{Name}->{content},
calls => (defined($zone->{Calls})) ? scalar(@{$zone->{Calls}->{Call}}) : 0,
status => $zone->{Status}->{content}
}; };
$self->{global}->{count}++; $self->{global}->{count}++;
} }
$self->{cache_name} = "cisco_vcs_" . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' . $self->{cache_name} = 'cisco_vcs_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' .
(defined($self->{option_results}->{filter_zone_name}) ? md5_hex($self->{option_results}->{filter_zone_name}) : md5_hex('all'))
} }
1; 1;
@ -188,21 +190,19 @@ __END__
=head1 MODE =head1 MODE
Check zones count and state. Check zones.
=over 8 =over 8
=item B<--warning-*> =item B<--filter-zone-name>
Threshold warning. Filter zones by name (can be a regexp).
Can be: 'zones-count', 'calls-count', 'searches-total' (/s), 'searches-dropped' (/s),
'searches-max-sub-search-exceeded' (/s), 'searches-max-targets-exceeded' (/s).
=item B<--critical-*> =item B<--warning-*> B<--critical-*>
Threshold critical. Thresholds.
Can be: 'zones-count', 'calls-count', 'searches-total' (/s), 'searches-dropped' (/s), Can be: 'zones-count', 'zone-calls-current', 'searches-total',
'searches-max-sub-search-exceeded' (/s), 'searches-max-targets-exceeded' (/s). 'searches-dropped', 'searches-maxsub-exceeded', 'searches-maxtargets-exceeded'.
=item B<--warning-status> =item B<--warning-status>

View File

@ -30,13 +30,13 @@ sub new {
bless $self, $class; bless $self, $class;
$self->{version} = '1.0'; $self->{version} = '1.0';
%{$self->{modes}} = ( $self->{modes} = {
'calls' => 'network::cisco::vcs::restapi::mode::calls', 'calls' => 'network::cisco::vcs::restapi::mode::calls',
'http-proxy-stats' => 'network::cisco::vcs::restapi::mode::httpproxystats', 'http-proxy-stats' => 'network::cisco::vcs::restapi::mode::httpproxystats',
'zones' => 'network::cisco::vcs::restapi::mode::zones', 'zones' => 'network::cisco::vcs::restapi::mode::zones'
); };
$self->{custom_modes}{xmlapi} = 'network::cisco::vcs::restapi::custom::xmlapi'; $self->{custom_modes}->{xmlapi} = 'network::cisco::vcs::restapi::custom::xmlapi';
return $self; return $self;
} }