Imported Upstream version 1.12

This commit is contained in:
Mario Fetka
2017-10-31 14:38:28 +01:00
commit ae1fc8494f
157 changed files with 35016 additions and 0 deletions

110
scripts/cacti_jmx4perl Executable file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/perl
# nagios: +epn
use FindBin qw ($Bin);
use JMX::Jmx4Perl::Nagios::CactiJmx4Perl;
# Create modue and immediately execute it
JMX::Jmx4Perl::Nagios::CactiJmx4Perl->new(@ARGV)->execute();
=head1 NAME
cacti_jmx4perl - Script for a Cacti Data Input Method
=head1 SYNOPSIS
# Print out used heap memory (absolute values)
cacti_jmx4perl --url http://localhost:8888/jolokia \
--name memory_used \
--mbean java.lang:type=Memory \
--attribute HeapMemoryUsage \
--path used
# Print out relative value
cacti_jmx4perl --url http://localhost:8888/jolokia \
--alias MEMORY_HEAP_USED \
--base MEMORY_HEAP_MAX
# Use predefined checks in a configuration file with a server alias Server
# alias is 'webshop', output is the number of requests per minute for the servlet
# 'socks_shop'
cacti_jmx4perl --config /etc/nagios/check_jmx4perl/tomcat.cfg
--server webshop \
--check tc_servlet_requests \
socks_shop
# Number of threads started within a minute
cacti_jmx4perl --url http://localhost:8888/jolokia \
--alias THREAD_COUNT_STARTED \
--delta 60
# Proxy-mode usage
cacti_jmx4perl --url http://localhost:8888/jolokia \
--alias MEMORY_HEAP_USED \
--critical 10000000 \
--target service:jmx:rmi:///jndi/rmi://bhut:9999/jmxrmi
=head1 DESCRIPTION
This script is a simplified version of C<check_jmx4perl> which does not check
for thresshold and prints out the measured data in a simplified format, which
can be used by Cacti (L<www.cacti.net>). For single checks, it simply returns
the number measured, for multi checks, the numbers are returned with labels and
space separated. See L<check_jmx4perl/"Multichecks"> for more about
multichecks.
Example:
$ cacti_jmx4perl --url http://localhost:8080/jolokia --alias MEMORY_HEAP_USED
15308376
$ cacti_jmx4perl -u http://localhost:8080/jolokia --config config/memory.cfg --check memory
Heap:15341168 Non-Heap:19450312
For the possible options and the configuration syntax, please refer to the
documentation of L<check_jmx4perl>. Certain options are I<not> available for this
Cacti Script, since they make no sense here:
=over
=item --warning
=item --critical
=item --unit
=item --null
=item --string
=item --numeric
=item --label
=back
=head1 LICENSE
This file is part of jmx4perl.
Jmx4perl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
jmx4perl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jmx4perl. If not, see <http://www.gnu.org/licenses/>.
=head1 AUTHOR
roland@cpan.org
=cut
1;

1911
scripts/check_jmx4perl Executable file

File diff suppressed because it is too large Load Diff

144
scripts/j4psh Executable file
View File

@@ -0,0 +1,144 @@
#!/usr/bin/perl
=head1 NAME
j4psh - A JMX Shell
=cut
use Getopt::Long
;
use strict;
use JMX::Jmx4Perl::Config;
use JMX::Jmx4Perl::J4psh;
use Config::General;
=head1 SYNOPSIS
j4psh [options] <server>
j4psh --help
j4psh --version
Options:
--user <user> Credential used for authentication
--password <pwd>
--proxy <url> URL to use as proxy proxy
--proxy-user <user> Authentication information for a proxy
--proxy-password <pwd>
--target <jmx-url> JSR-160 JMX Service URL to be used as the target server
--target-user <user> Credential for the target server if --target is given
--target-password <pwd>
--option key=val Options for tuning the output of jmx4perl. Known keys are
format : Either 'json' or 'data'
booleans : Pair of strings separated by slash to use for printing
boolean values (Default: [true]/[false])
indent : Space indent when printing complex data structures
--config <cfg> Path to an optional configuration file (default: ~/.j4p). Can be a directory
in which case <dir>/jmx4perl.cfg is used.
--color [yes|no] Color option (default: yes)
An optional argument can be used to directly connect to an agent URL or
symbolic name as defined in the configuration file. If not given, the shell
does no initial connect.
=head1 DESCRIPTION
B<j4psh> is a frontend to C<JMX::Jmx4Perl> providing an interactive shell for
accessing JMX MBeans on a remote Java server.
=over 4
=item *
Readline and history support based on GNU Readline/History as known from other
shells like 'bash'. When GNU Readline is not available, a pure Perl Module is
used instead.
=item *
Context sensitive argument completion, e.g. on MBean names and attributes.
=item *
Colored output (can be switched off)
=item *
Multi-Server support
=item *
Remote operation via HTTP(S)
=back
=cut
my %opts = ();
my $result = GetOptions(\%opts,
"user|u=s","password|p=s",
"proxy=s",
"proxy-user=s","proxy-password=s",
"config=s",
"version!",
"color=s",
"option|opts|o=s%",
"target|t=s","target-user=s","target-password=s",
"help|h!" => sub { &Getopt::Long::HelpMessage() }
);
my $server = shift;
if ($opts{version}) {
print "j4psh ",$JMX::Jmx4Perl::VERSION,"\n";
exit(0);
}
# Parse configuration files
my $j4p_config = new JMX::Jmx4Perl::Config($opts{config});
# Create global context object
my $j4psh = new JMX::Jmx4Perl::J4psh(initial_server => $server,config => $j4p_config,args => \%opts);
# Let the shell run
$j4psh->run;
=head1 LICENSE
This file is part of jmx4perl.
Jmx4perl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
jmx4perl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jmx4perl. If not, see <http://www.gnu.org/licenses/>.
A commercial license is available as well. Please contact roland@cpan.org for
further details.
=head1 PROFESSIONAL SERVICES
Just in case you need professional support for this module (or Nagios or JMX in
general), you might want to have a look at
http://www.consol.com/open-source-monitoring/consulting/. Contact roland.huss@consol.de for
further information (or use the contact form at http://www.consol.com/contact/)
=head1 AUTHOR
roland@cpan.org
=cut
1;

779
scripts/jmx4perl Executable file
View File

@@ -0,0 +1,779 @@
#!/usr/bin/perl
=head1 NAME
jmx4perl - JMX access tools and modules
=cut
use Getopt::Long;
use FindBin;
use JMX::Jmx4Perl;
use JMX::Jmx4Perl::Util;
use JMX::Jmx4Perl::Request;
use JMX::Jmx4Perl::Alias;
use strict;
use Carp;
use JSON;
use Data::Dumper;
my %COMMANDS =
(
info => \&command_info,
list => \&command_list,
attributes => \&command_attributes,
read => \&command_read,
get => \&command_read,
write => \&command_write,
set => \&command_write,
exec => \&command_exec,
call => \&command_exec,
search => \&command_search,
version => \&command_version
);
my %opts = ();
my $result = GetOptions(\%opts,
"user|u=s","password|p=s",
"proxy=s",
"proxy-user=s","proxy-password=s",
"target|t=s","target-user=s","target-password=s",
"product=s",
"config=s",
"method=s",
"verbose|v!",
"shell|s=s",
"version!",
"history!",
"legacy-escape!",
"option|opts|o=s%",
"help|h!" => sub { Getopt::Long::HelpMessage() }
);
my $url;
my $command;
my @args;
if (lc $ARGV[0] eq "aliases") {
command_aliases();
exit(0);
} elsif (lc $ARGV[0] eq "encrypt") {
command_encrypt($ARGV[1]);
exit(0);
} elsif (@ARGV == 1) {
$command = "info";
$url = $ARGV[0];
} else {
$url = shift @ARGV;
$command = lc shift @ARGV;
@args = ( @ARGV );
}
if ($opts{version}) {
if ($url) {
$command = "version";
} else {
print "jmx4perl ",$JMX::Jmx4Perl::VERSION,"\n";
exit(0);
}
}
my $sub = $COMMANDS{$command} || die "No command '",$command,"' known. See --help for assistance\n";
my $config = new JMX::Jmx4Perl::Config($opts{config});
my $jmx_args = &_get_args_for_jmx4perl($url,$config,\%opts);
my $jmx4perl = new JMX::Jmx4Perl($jmx_args);
&{$sub}($jmx4perl,@args);
=head1 SYNOPSIS
jmx4perl .... http://server:8080/jolokia ["info"]
jmx4perl .... <agent-url> read <mbean-name> <attribute-name> [path]
jmx4perl .... <agent-url> write <mbean-name> <attribute-name> <value> [path]
jmx4perl .... <agent-url> exec <mbean-name> <operation> <arg1> <arg2> ...
jmx4perl .... <agent-url> search <mbean pattern>
jmx4perl .... <agent-url> list [<domain-name>[:<mbean name>]]
jmx4perl .... <agent-url> attributes [max-depth max-list-size max-objects]
jmx4perl .... aliases
jmx4perl .... encrypt <password>
jmx4perl --help
jmx4perl --version [<agent-url>]
Options:
--product <id> Product to use for aliasing (ommits autodetection)
--user <user> Credential used for authentication
--password <pwd>
--proxy <url> URL to proxy
--proxy-user <user> Authentication information for a proxy
--proxy-password <pwd>
--target <jmx-url> JSR-160 JMX Service URL to be used as the target server
--target-user <user> Credential for the target server if --target is given
--target-password <pwd>
--config <cfg> Path to an optional configuration file (default: ~/.j4p). Can be a directory
in which case <dir>/jmx4perl.cfg is used.
--history Print out the history of return values (if switched on and present)
--legacy-escape Used for contacting pre 1.0 Jolokia agent for MBeans containing
slashes in their name.
--method <get|post> Method to be used for HTTP request ("get" or "post")
--option key=val Options for tuning the output of jmx4perl. Known keys are
format : Either 'json' or 'data'
booleans : Pair of strings separated by slash to use for printing
boolean values (Default: [true]/[false])
indent : Space indent when printing complex data structures
--verbose Print out more information
=head1 DESCRIPTION
B<jmx4perl> is a command line utility for an easy access of an instrumented
application server. Before you can use this tool, you need to deploy a small
agent application. In the following C<agent-url> is the URL for accessing this
agent. If you use a configuration file, you can use also a symbolic name as
stored in the configuration file. See L<JMX::Jmx4Perl::Manual> for details.
With the C<--option> (or C<-o> for short) the output of B<jmx4perl> can be
tuned. I.e. the way boolean values are printed can be tuned as well as the
data format to use for complex data structure. The known options are
=over
=item format
the value an be either C<json> or <data> for printing out complex data as JSON
or as a Perl data structure. Default is "data".
=item booleans
Specify the pair of strings to use for boolean values for the C<data> output
format. The value of this option should be given as a string separated with a
C</>. The default value is C<[true]/[false]>.
=item method
Specify the HTTP method to use for requesting the server. This can either be
C<get> or C<post>. By default "get" is used.
=item legacy-escape
Prior to version 1.0 Jolokia used a different escaping scheme for GET requests
which contains slashes. This option must be used, when the server-side agent
has a version < 1.0 and the MBean name contains slashes ("/"). Alternatively,
C<--method post> can be used, since the post method doesn't suffer from any
escaping issues.
=item indent
Number of spaces to use for indenting the output of complex data
structures. Default are 4 spaces.
=back
The options can be also put into the configuration file in a section called
C<Jmx4Perl>. For example:
<Jmx4Perl>
# 'json' or 'data'
Format json
# Boolean values: Default is [true]/[false]
Booleans 0/1
# Number of spaces to indent for complex
# data structures
Indent 4
</Jmx4Perl>
B<jmx4perl> serves also an example of how to use the L<JMX::Jmx4Perl> package.
See its documentation for more details on how to embed JMX access into your
programs.
=cut
# ===================================================================================================
# Commands:
=head1 COMMANDS
=head2 info
If you use jmx4perl without any command or with C<info> as command, you get a
description about the server, including the application server's product name
and version. This works by autodetection and only for the supported application
servers (see L<JMX::Jmx4Perl::Manual> for a list of supported products). The
only argument required is the url which points to the deployed jmx4perl agent.
With C<--verbose> C<info> prints the system properties and runtime arguments as
well.
=cut
sub command_info {
my $jmx = shift;
print $jmx->info($opts{verbose});
}
=head2 list
List meta data of all registered mbeans on the target application server. This
includes attributes and operations along whith their descriptions and
parameters (as far as they are provided by mbean's info).
You can provide an inner path as an additional argument as well. See
L<JMX::Jmx4Perl::Request> for an explanation about inner paths (in short, it's
some sort of XPath expression which selects only a subset of all MBeans and
their values). See L<JMX::Jmx4Perl>, method "list()" for a more rigorous
documentation abouting listing of MBeans.
=cut
sub command_list {
my ($jmx,$path) = @_;
$path =~ s|:|/|;
my $req = JMX::Jmx4Perl::Request->new(LIST,$path);
my $resp = $jmx->request($req);
&_check_for_error($resp);
# Show list of beans
print $jmx->formatted_list($resp);
}
=head2 attributes
Show all attributes of all registerd mbeans and their values. For simple scalar
values they are shown on one line, for more complex data structures,
L<Data::Dumper> is used. Please note, that it is normal, that for certain
attributes an error is returned (i.e. when this attribute is not implemented on
the server side e.g. or an MXMbean). To see the full server side stacktrace for
this errors, use C<--verbose> as command line option
The attribute list can get quite large (moren than 200 MB for JBoss 5). To
restrict the output you can use the following extra optional parameters (given
in this order):
=over
=item maxDepth
Maximum nesting level of the returned JSON structure for a certain MBean
(default: 5)
=item maxCollectionSize
Maximum size of a collection after which it gets truncated (default: 150)
=item maxObjects
Maximum overall objects to fetch for a certain MBean (default: 1000)
=back
In the case of truncation, the JSON answer contains marker entries like
C<[Object limit exceeded]> or C<[Depth limit ...]>. Loops are detected, too
which results in markers of the form C<[Reference ...]>
=cut
sub command_attributes {
my $jmx = shift;
my $max_depth = defined($_[0]) ? $_[0] : 6;
my $max_list_size = defined($_[1]) ? $_[1] : 150;
my $max_objects = defined($_[2]) ? $_[2] : 100000;
my $mbeans = $jmx->search("*:*");
for my $mbean (@$mbeans) {
my $request = JMX::Jmx4Perl::Request->new(READ,$mbean,undef,{maxDepth => $max_depth,
maxObjects => $max_objects,
maxCollectionSize => $max_list_size,
ignoreErrors => 1});
eval {
my $response = $jmx->request($request);
if ($response->is_error) {
print "\nERROR: ",$response->error_text,"\n";
if ($opts{verbose}) {
if ($response->stacktrace) {
print $response->stacktrace;
} else {
print _dump($response);
}
}
} else {
my $values = $response->value;
if (keys %$values) {
for my $a (keys %$values) {
print "$mbean -- $a";
my $val = $values->{$a};
if (_is_object($val)) {
my $v = _dump($val);
$v =~ s/^\s*//;
print " = ",$v;
} else {
print " = ",_dump_scalar($val),"\n";
}
}
}
}
};
if ($@) {
print "\nERROR: ",$@,"\n";
}
}
}
=head2 read / get
Read an JMX attribute's value and print it out. The required arguments are the
MBean's name and the attribute's name. Additionally, you can provide a I<path>
within the return value to pick a sub-value. See L<JMX::Jmx4Perl::Request> for a
detailed explanation of paths.
The MBean's name and the attribute can be substituted by an
alias name, too.
For a single value, the value itself is printed (without additional newline),
for a more complex data structure, L<Data::Dumper> is used.
If the option C<--history> is given and history tracking is switched on (see
below), then the stored history is printed as well.
=cut
sub command_read {
my $resp = &_get_attribute(@_);
&_check_for_error($resp);
&_print_response($resp);
}
=head2 write / set
Write a JMX attribute's value and print out the value as it is returned from
the server. The required arguments are the MBean's name, the attribute and the
value to set. Optionally, a inner path can be provided as well in which case a
inner value is set. The MBean's name and the attribute can be substituted by an
alias name, too. See also L</"aliases"> for getting all available aliases.
The old value of the attribute (or the object pointed to by the inner path) is
printed out in the same as for L</"read">
To set a C<null> value use "[null]" as argument, to set an empty string use an
empty argument (i.e. C<""> on the command line). These values are interpreted
special, so you can't use them literally as values.
If the option C<--history> is given and history tracking is switched on (see
below), then the stored history is printed as well.
=cut
sub command_write {
my $resp = &_set_attribute(@_);
&_check_for_error($resp);
&_print_response($resp);
}
=head2 exec / call
Execute a JMX operation. The required arguments are the MBean's name, the name
of the operation to execute and the arguments required for this operations
(which can be empty if the operation doesn't take any arguments). The return
value is the return value of the operation which can be C<undef> in the case of
a void operation.
A operation alias can also be used for the MBean's name and operation.
To use a C<null> argument use "[null]", to set an empty string as argument use
an empty argument (i.e. C<"">) on the command line. These values are
interpreted special, so you can't use them literally as values.
For a single return value, the value itself is printed (without additional
newline), for a more complex data structure, L<Data::Dumper> is used.
If the option C<--history> is given and history tracking is switched on (see
below), then the stored history is printed as well.
=cut
sub command_exec {
my $resp = &_exec_operation(@_);
&_check_for_error($resp);
&_print_response($resp);
}
=head2 aliases
Print out all known aliases. See L<JMX::Jmx4Perl::Manual> for a discussion
about aliases. In short, you can use an alias as a shortcut for an MBean's
and attribute's name.
=cut
sub command_aliases {
&JMX::Jmx4Perl::Alias::help;
}
=head2 search
Search for a certain MBean. As argument you should provide a pattern like
C<*:j2eeType=Servlet,*>. I.e you can use the wildcard C<*> for the domain
name part, and properties as a whole (but not within a key=property tuple). See
L<http://java.sun.com/j2se/1.5.0/docs/api/javax/management/ObjectName.html> for
a complete explanation of how a pattern can look like. As a result of this
operation, a list of fully qualified MBean names is printed out line by line
which match the given pattern.
=cut
sub command_search {
my $resp = &_search_attribute(@_);
return if $resp->status == 404;
&_check_for_error($resp);
my $val = $resp->value;
$val = [ $val ] unless ref($val) eq "ARRAY";
for my $l (@$val) {
print $l,"\n";
}
}
=head2 encrypt
Encrypt a given password so that it can be stored in its encrypted form in a
configuration file. Please note, that this is by no means secure and only usual
to avoid casual discovery of the password. Since jmx4perl acts as a client it
needs to be able to decrypt the password on its own when contacting the agent,
so it is a simple symmetric encryptions. The password printed out can be used
as C<Password> value for HTTP authentication and HTTP proxy authentication in
configuration files or at the command line.
=cut
sub command_encrypt {
require JMX::Jmx4Perl::Agent;
my $val = shift;
my $enc = JMX::Jmx4Perl::Agent::encrypt($val);
print $enc,"\n";
}
=head1 HISTORY TRACKING
The agent knows about a history mode, which can remember a certain
amount return values from previous requests. This mode can be switched on/off
on a per attribute (+ inner path) and operation basis. By default it is
switched off completely. You can switch in on by executing the
C<JMX4PERL_HISTORY_MAX_ATTRIBUTE> and C<JMX4PERL_HISTORY_MAX_OPERATION>
operation with L</"exec"> commands. This is best explained by some example:
jmx4perl exec JMX4PERL_HISTORY_MAX_ATTRIBUTE java.lang:type=Memory HeapMemoryUsage used 10 <agent-url>
This switches on tracking of this particular attribute. I.e. each time a
C<read> request is performed, the value is remembered along with a timestamp on
the server side. At maximum 10 entries are kept, the oldest entries get shifted
out after the eleventh read. Setting the value to C<0> will remove the history
completely. You can't set the limit beyond a certain hard limit, which can be
found as attribute under the alias
C<JMX4PERL_HISTORY_MAX_ENTRIES>. Unfortunately, one can not use an alias yet
for the arguments of C<JMX4PERL_HISTORY_MAX_ATTRIBUTE>. Also note, if you don't
has an inner path, you need to use a C<[null]> as the argument before the max
entry number.
For completely resetting the history, use
jmx4perl exec JMX4PERL_HISTORY_RESET <agent-url>
If you are curious about the size of the history for all entries, use
jmx4perl read JMX4PERL_HISTORY_SIZE <agent-url>
This will print out the history size in bytes.
=cut
# Command for printing out the version
sub command_version {
my $jmx = shift;
print "jmx4perl ",$JMX::Jmx4Perl::VERSION,"\n";
my $resp = $jmx->request(new JMX::Jmx4Perl::Request(AGENT_VERSION));
#print Dumper($resp);
if ($resp->is_error) {
die "Cannot fetch agent version: ",$resp->error_text;
}
my $val = $resp->{value};
print "Jolokia Agent " . $val->{agent} . " (protocol: " . $val->{protocol} . ")\n";
exit(0);
}
# =============================================================================
sub _check_for_error {
my $resp = shift;
if ($resp->is_error) {
print STDERR "ERROR: ",$resp->error_text,"\n";
if ($opts{verbose}) {
print STDERR "Content:\n" . $resp->{content} if $resp->{content};
if ($resp->stacktrace) {
print STDERR "Server Stacktrace:\n";
print STDERR $resp->stacktrace;
}
}
exit 1;
}
}
sub _is_object {
return JMX::Jmx4Perl::Util->is_object_to_dump(shift);
}
sub _dump_scalar {
return JMX::Jmx4Perl::Util->dump_scalar(shift,_get_opt_or_config("Booleans"));
}
sub _dump {
my $value = shift;
my $format = $opts{format} || "data";
return JMX::Jmx4Perl::Util->dump_value($value,{format => _get_opt_or_config("Format"),
booleans => _get_opt_or_config("Booleans"),
indent => _get_opt_or_config("Indent")
});
}
sub _get_opt_or_config {
my $key = shift;
if (defined($opts{option}) && defined($opts{option}->{lc $key})) {
return $opts{option}->{lc $key};
} else {
my $j4pconfig = $config->{jmx4perl} || {};
return $j4pconfig->{lc $key};
}
}
sub _has_tty {
return -t STDOUT;
}
sub _print_response {
my $resp = shift;
my $val = $resp->value;
if (_is_object($val)) {
print _dump($val);
} else {
print _dump_scalar($val);
print "\n" if &_has_tty;
}
if ($opts{history} && $resp->history) {
print "\nHistory:\n";
for my $entry (@{$resp->history}) {
my $time = localtime($entry->{timestamp});
my $value = $entry->{value};
if (_is_object($value)) {
print $time,"\n";
print _dump($value);
print "\n";
} else {
printf " %s : %s\n",$time,_dump_scalar($value);
}
}
}
}
sub _get_attribute {
my $jmx = shift;
my ($mbean,$attribute,$path) = _extract_get_set_parameter($jmx,"get",@_);
if (ref($mbean) eq "CODE") {
return $jmx->delegate_to_handler($mbean,@args);
}
my $req = new JMX::Jmx4Perl::Request(READ,$mbean,$attribute,$path);
return $jmx->request($req);
}
sub _set_attribute {
my $jmx = shift;
my ($mbean,$attribute,$path,$value) = _extract_get_set_parameter($jmx,"set",@_);
if (ref($mbean) eq "CODE") {
return $jmx->delegate_to_handler($mbean,@args);
}
my $req = new JMX::Jmx4Perl::Request(WRITE,$mbean,$attribute,$value,$path);
return $jmx->request($req);
}
sub _search_attribute {
my $jmx = shift;
my ($pattern) = @_;
my $req = new JMX::Jmx4Perl::Request(SEARCH,$pattern);
return $jmx->request($req);
}
sub _exec_operation {
my $jmx = shift;
my ($mbean,$operation,@args) = @_;
my $alias = JMX::Jmx4Perl::Alias->by_name($mbean);
if ($alias) {
croak $alias->{alias}, " is not an operation alias" unless $alias->{type} eq "operation";
unshift @args,$operation if $operation;
($mbean,$operation) = $jmx->resolve_alias($alias);
if (ref($mbean) eq "CODE") {
return $jmx->delegate_to_handler($mbean,@args);
}
die "Alias ",$alias->{alias}," is not available for product ",$jmx->product,"\n" unless $mbean;
} else {
&_validate_mbean_name($mbean);
die "ERROR No operation given for MBean $mbean given\n" unless $operation;
}
print "$mbean $operation\n";
my $req = new JMX::Jmx4Perl::Request(EXEC,$mbean,$operation,@args);
return $jmx->request($req);
}
sub _extract_get_set_parameter {
my ($jmx,$mode,$mbean,$attribute,$path_or_value,$path) = @_;
my $value;
$path = $path_or_value if $mode eq "get";
$value = $path_or_value if $mode eq "set";
croak "No MBean name or alias given\n" unless $mbean;
# Try to resolve the MBean name as an alias. If this works, we are using
# this alias.
my $alias = JMX::Jmx4Perl::Alias->by_name($mbean);
if ($alias) {
# Shift arguments
$path = $attribute if $mode eq "get"; # path comes after alias
if ($mode eq "set") {
$path = $value;
$value = $attribute;
}
my ($o,$a,$p) = $jmx->resolve_alias($alias);
die "Alias ",$alias->{alias}," is not available for product ",$jmx->product,"\n" unless $o;
if ($path) {
$p = $p ? $p . "/" . $path : $path;
}
return ($o,$a,$p,$value);
} else {
&_validate_mbean_name($mbean);
die "ERROR No attribute for MBean $mbean given\n" if (!defined($attribute) && $mode eq "set");
return ($mbean,$attribute,$path,$value);
}
}
sub _validate_mbean_name {
my $mbean = shift;
die "ERROR: Invalid format for MBean name $mbean (Did you misspelled an alias name ?)\n" if
($mbean !~ /^[^:]+:[^:]+$/ || $mbean !~ /:([^=]+)=/);
}
sub _get_args_for_jmx4perl {
my $url = shift;
my $config = shift;
my $opts = shift;
# Try provided first argument as server name first in a
# given configuration
my $ret;
my $server_config = $config->get_server_config($url);
if ($server_config && $server_config->{url}) {
print "Taking ",$server_config->{url}, " from configuration for $url\n" if $opts->{verbose};
&_verify_url($server_config->{url});
# Use server configs as default
$ret = { server => $url, config => $config };
} else {
&_verify_url($url);
$ret = { url => $url };
}
# Basic options to take over literally
for my $arg (qw(product user password verbose method legacy-escape)) {
if (defined($opts->{$arg})) {
$ret->{$arg} = $opts->{$arg};
}
}
# Take proxy and target from config
if ($server_config) {
if ($server_config->{proxy}) {
my $proxy = $server_config->{proxy};
die "Old proxy syntax (Proxy,Proxy_User,Proxy_Password) not supported in config anymore"
unless ref($proxy) eq "HASH";
$ret->{proxy} = $proxy;
}
if ($server_config->{target}) {
$ret->{target} = $server_config->{target}
}
}
# Overwrite with command line arguments
if (defined($opts->{proxy})) {
my $proxy = {};
$proxy->{url} = $opts->{proxy};
for my $k (qw(proxy-user proxy-password)) {
$proxy->{$k} = defined($opts->{$k}) if $opts->{$k};
}
$ret->{proxy} = $proxy;
}
if (defined($opts->{target})) {
$ret->{target} = {
url => $opts->{target},
$opts->{'target-user'} ? (user => $opts->{'target-user'}) : (),
$opts->{'target-password'} ? (password => $opts->{'target-password'}) : (),
};
}
return $ret;
}
sub _verify_url {
my $url = shift;
unless ($url =~ m|^\w+://|) {
my $text = "No url or server name given for command. See --help for assistance.\n";
my $last = $#ARGV >= 0 ? $ARGV[$#ARGV] : undef;
if ($last && $last =~ m|^\w+://| && $last ne $url) {
$text .= "Please note, that the URL must be given as first argument, not as last.\n";
}
die $text;
}
}
=head1 SEE ALSO
L<JMX::Jmx4Perl> - Entry point for programmatic JMX access which is used by
this tool.
L<check_jmx4perl> - a production ready Nagios check using L<JMX::Jmx4Perl>
L<jolokia> - utility for downloading and managing Jolokia agents
L<j4psh> - readline based JMX shell with context sensitive command line
completion.
=head1 LICENSE
This file is part of jmx4perl.
Jmx4perl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
jmx4perl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jmx4perl. If not, see <http://www.gnu.org/licenses/>.
=head1 AUTHOR
roland@cpan.org
=cut

647
scripts/jolokia Executable file
View File

@@ -0,0 +1,647 @@
#!/usr/bin/perl
=head1 NAME
jolokia - Utility for managing Jolokia agents used by jmx4perl
=cut
use Getopt::Long;
use JMX::Jmx4Perl::Agent::Jolokia::Meta;
use JMX::Jmx4Perl::Agent::Jolokia::DownloadAgent;
use JMX::Jmx4Perl::Agent::Jolokia::Logger;
use JMX::Jmx4Perl::Agent::Jolokia::ArtifactHandler;
use JMX::Jmx4Perl::Agent::Jolokia::WebXmlHandler;
use JMX::Jmx4Perl;
use Digest::MD5;
use Data::Dumper;
use strict;
=head1 SYNOPSIS
# Execute command 'command' with options and additional, command specific
# arguments
jolokia [options] <command> <arg1> <arg2> ...
# Download the latest Jolokia WAR agent compatible with this jmx4perl release
# into the local directory as 'jolokia.war'
jolokia download
# Print information about a downloaded agent (i.e. its version)
jolokia info jolokia.war
# Repackage the agent to include a security policy
jolokia repack --policy jolokia.war
# Jmx4Perl version
jolokia --version
# Online help
jolokia --help
Options:
Command 'download':
--agent <type>[:<version>] Agent to download. <type> must be one of "war", "osgi",
"osgi-bundle", "mule" or "jvm". An optional Jolokia version
can be added after a colon.
--outdir <dir> Output directory for the agent downloaded (default: ".")
--repository <repo-url> Repository URL from where to fetch the Jolokia agent.
(default is taken from meta data)
--template <name>[:<version>] Download a template with given name and optional version. E.g.
"jolokia-access.xml:0.83". If used with --agent, the same version
as for the agent is used by default
--policy Same as --template jolokia-access.xml
Command 'info':
--verify Check signature of given file
--policy Print out an embedded jolokia-access.xml
Command 'repack':
--policy Adds a jolokia-access.xml policy file, which is in the current
directory. --no-policy removes the policy file.
--policy-file <policy file> Alternate policy file to use (implies --policy)
--security Add security to the web.xml with role 'jolokia' by default.
Use no-security in order to remove security section completely
--security-role <role> Select a different role for WEB security. Implies --security
--no-jsr160-proxy Remove the JSR-160 proxy declaration from web.xml. Re-add with
--jsr160-proxy
General:
--quiet No output on the standard out
--verbose Print verbose
--no-color Don't use colors
--no-cache Fetch meta information afresh from www.jolokia.org
--proxy Proxy-URL for HTTP(S) requests
--proxy-user Proxy user for proxy authentication
--proxy-password Proxy password for proxy authentication
--help Print online help (and exit)
--version Jmx4Perl version
=head1 DESCRIPTION
B<jolokia> is a command line utility for managing the Jolokia agent,
which is used by jmx4perl for accessing remote JMX information. Several
commands are available
=over
=item download
This mode allows for downloading the latest Jolokia agent version compatible
with this Jmx4Perl installation or any other agent version. PGP is used
optionally for verifying the integrity of the downloaded artifacts.
=item info
For a given Jolokia agent, this manager gives you information about the version
of the agent and also allows for PGP validation.
=item repack
A Jolokia agent can be repacked in order to add a policy file or to manipulate
the internal web.xml with this mode.
=back
C<download> ist the default mode when no non-opt argument is given, if a single
argument is given and this single argument is not one of the modes above, C<info> is
used as the default command and the single argument is the file to examine.
=head1 META-DATA
Meta-data about the available Jolokia agents and their compatibility to given
Jmx4Perl versions is obtained from L<http://www.jolokia.org/jolokia.meta>. This
meta data is cached locally in F<~/.jolokia_meta> and only fetched once a
day. The meta download can be forced by using the option C<--no-cache>.
=head1 VALIDATION
B<jolokia> uses PGP for validating all files downloaded. For this to work,
either the CPAN module L<Crypt::OpenPGP> or GnuPG (L<http://www.gnupg.org/>)
must be installed. If it is not available, validation falls back to simple
checksum validation with a SHA1 alogrithm, or, if this is not possible to an
MD5 check. Since the checksums are also downloaded over an insecure channel,
using PGP is highly recommended. The public key used for the signature check is
contained locally in the modules so there is no need to add the key manually or
to download it from an PGP key server. I.e. if GnuPG is used, the key will be
added to the local keystore for the first validation.
=head1 COMMANDS
=cut
# Agent manager for
# - adding security constraints
# - manipulating the policy file
# - deploying it to the target server
my %opts = ();
GetOptions(\%opts,
"agent|a=s",
"template=s",
"outdir|o=s",
"repository|r=s",
"policy!",
"policy-file:s",
"quiet|q",
"version|v",
"verify!",
"verbose",
"color!",
"proxy=s",
"proxy-user=s",
"proxy-password=s",
"cache!",
"security!",
"security-role=s",
"jsr160-proxy!",
"help|h" => sub { Getopt::Long::HelpMessage() },
) || die "Use --help for available options\n";
if ($opts{version}) {
print "jolokia ",$JMX::Jmx4Perl::VERSION,"\n";
exit(0);
}
my %COMMANDS =
(
download => \&command_download,
info => \&command_info,
repack => \&command_repack
);
my $mode;
if (!@ARGV) {
$mode = "download";
} elsif (!$COMMANDS{$ARGV[0]}) {
$mode = "info";
} else {
$mode = shift @ARGV;
}
my $command = $COMMANDS{$mode} || die "Unknown mode " . $mode . "\n";
# TODO: Add UserAgent Config here
my $ua_config = {
$opts{proxy} ? (http_proxy => $opts{proxy}, https_proxy => $opts{proxy}) : (),
$opts{'proxy-user'} ? (proxy_user => $opts{'proxy_user'}) : (),
$opts{'proxy-password'} ? (proxy_password => $opts{'proxy_password'}) : (),
};
my $logger = new JMX::Jmx4Perl::Agent::Jolokia::Logger
(
quiet => $opts{quiet},debug => $opts{verbose},
color => defined($opts{color}) ? $opts{color} : 1
);
my $meta = new JMX::Jmx4Perl::Agent::Jolokia::Meta
(
logger => $logger,
ua_config => $ua_config,
force_load => defined($opts{cache}) ? !$opts{cache} : 0
);
my $verifier = new JMX::Jmx4Perl::Agent::Jolokia::Verifier
(
logger => $logger,
ua_config => $ua_config
);
$command->($meta,\%opts,@ARGV);
# ===========================================================
=head2 download
This commands allows for downloading a certain Jolokia agent from Jolokia's
Maven repository. The repository URL is taken from the meta descriptor, but can
be overridden with the C<--repository> option. Agents come in several flavors:
=over
=item * war
The WAR agent is the most popular one and is used for instrumenting an JEE
application server. It is a simple web application which needs to deployed on
the target server
=item * osgi, osgi-bundle
The OSGi agents can be used to access OSGi containers
=item * mule
For accessing a Mule ESB, this agent is the proper choice
=item * jvm
For all other Java server, which don't contain a servlet container, this agent
can be used. The only prerequisite is, that the application must run with an
Oracle Java 6 virtual machine
=back
Much more information about those agents can be found at
L<http://www.jolokia.org/agent.html>.
By default, the war agent is downloaded. The agent type ("war", "osgi",
"osgi-bundle", "mule" or "jvm" can be specified with the C<--agent> option.
Also by default, the latest agent version compatible with the installed
Jmx4Perl release is downloaded. A specific version can be given on the command
line also with the C<--agent> option, added after the agent type with a
':'. E.g. C<--agent osgi:0.82> will download the OSGi agent with version 0.82.
The output directory for the agent can be specified with the C<--outdir>
option. By default, the agent is stored in the current working directory.
A template can be downloaded with C<--template>. This option uses the same
syntax as C<--agent>, i.e. a version number can be optionally defined. If no
version number is provided, either the default template is downloaded, or, if
used together with C<--agent>, the template matching the agent's version is
used.
=cut
sub command_download {
my ($meta,$args) = @_;
fatal("Cannot load meta data for download ... Aborting") if !$meta->load;
my ($agent,$agent_version) = parse_version("agent",[keys %{$meta->get("mapping")}],$args->{agent});
my $t = $args->{template} || ($args->{policy} ? "jolokia-access.xml" : undef);
my ($template,$template_version) = parse_version("template",[keys %{$meta->get("templates")}],$t);
$agent = "war" if (!$template && !$agent);
$agent_version = agent_version($meta,$agent_version);
# Dynamic switching for pre-1.0 clients
if ($agent =~ /^(jvm|jdk6)$/) {
$agent = $agent_version < "1.0.0" ? "jdk6" : "jvm";
}
$template_version = $agent_version if ($template && !$template_version);
download_agent($meta,$agent,$agent_version,$args) if $agent;
download_template($meta,$args,$template,$template_version) if $template;
}
sub parse_version {
my $type = shift;
my $keys = shift;
my $spec = shift;
return (undef,undef) unless $spec;
my $regexp = '^(' . join("|",@$keys) . '):?([\d\.]*(-SNAPSHOT)?)\s*$';
if ($spec =~ $regexp) {
return ($1,$2);
} else {
$logger->error("Invalid $type specification \"$spec\". Known ${type}s are: ",join(", ",sort @$keys)) && exit(1);
}
}
sub agent_version {
my $meta = shift;
my $version = shift;
if ($version) {
verify_version($meta,$version);
return $version;
} else {
$version = $meta->latest_matching_version($JMX::Jmx4Perl::VERSION);
fatal("Cannot find compatible Jolokia version for Jmx4Perl ",$JMX::Jmx4Perl::VERSION)
unless $version;
}
}
sub download_template {
my $meta = shift;
my $args = shift;
my $template = shift;
my $version = shift;
my $url = $meta->template_url($template,$version);
fatal("No template $template known") unless $url;
my $file = path($args,$template);
$logger->info("Downloading ","[em]",$template,"[/em]", " version ",$version);
download($url,$file,$args);
verify_signature($file,$url);
}
sub path {
my $args = shift;
my $file = shift;
my $dir = $args->{outdir} || ".";
return $dir . "/" . $file;
}
sub download_agent {
my $meta = shift;
my $agent = shift;
my $version = shift;
my $args = shift;
my $is_snapshot = $version =~ /(.*?)-SNAPSHOT$/;
my $repositories;
if ($args->{repository}) {
$repositories = [ $args->{repository} ];
} else {
$repositories = $is_snapshot ? $meta->get('snapshots-repositories') : $meta->get('repositories');
}
$logger->info("Using ","[em]","Jolokia $version","[/em]",
" for ","[em]","Jmx4Perl $JMX::Jmx4Perl::VERSION","[/em]");
for my $repository (@$repositories) {
eval {
my $mapping = $meta->get("mapping");
my $full_version = $is_snapshot ? get_snapshot_version($meta,$repository,$agent,$version,$args) : $version;
my $download_url = get_download_url($meta,$repository,$agent,$full_version);
my $file = path($args,$mapping->{$agent}->[2]);
$logger->info("Downloading ","[em]",$agent," agent","[/em]", " version ",$version," from repository " . $repository);
download($download_url,$file,$args);
verify_signature($file,$download_url);
};
if ($@) {
print "Cannot fetch from $repository: " . $@ . "Trying next ...\n";
} else {
return;
}
}
$logger->error("Couldn't download a $agent agent from any these repositories:\n ",join("\n ",@$repositories));
die "\n";
}
=head2 info
In order to determine the version number of an already downloaded agent, the
C<info> command can be used. It takes as single argument the path to the agent,
e.g.
jolokia info ./jolokia.war
The output contains information about the agent's type and version, whether a
security policy file is installed, if authentication is switched on and if the
JSR160 proxy is active.
With the option C<--verify> an additional signature check can be performed,
where the signature is fetched from the Jolokia repository.
C<info> is the default command if a single file argument is given (i.e. the
example above could be abreviated to C<jolokia ./jolokia.war>).
If the option <--policy> is provided, an included Jolokia policy file will be
printed out (if any).
=cut
sub command_info {
my ($meta,$args,$file) = @_;
my $handler = new JMX::Jmx4Perl::Agent::Jolokia::ArtifactHandler(logger => $logger,
meta => $meta,file => $file);
$meta->load;
if ($args->{policy}) {
my $policy = $handler->get_policy;
fatal("No jolokia-access.xml embedded in $file") unless $policy;
print $policy;
return;
}
my $ret = $handler->info;
$logger->info("Type: ","[em]",$ret->{type},"[/em]");
$logger->info("Version: ","[em]",$ret->{version},"[/em]");
my $policy = $handler->has_policy;
$logger->info("Policy: ",$policy ? ("[em]","jolokia-access.xml","[/em]"," embedded") : "No security policy installed");
if ($ret->{type} eq "war") {
my $webxml_handler = new JMX::Jmx4Perl::Agent::Jolokia::WebXmlHandler(logger => $logger);
my $webxml = $handler->extract_webxml;
my $auth = $webxml_handler->has_authentication($webxml);
$logger->info("Security: ",$auth ? ("Authentication enabled for role ","[em]",$auth,"[/em]") : "No authentication enabled");
my $jsr160 = $webxml_handler->has_jsr160_proxy($webxml);
$logger->info("Proxy: ","JSR-160 proxy is ",$jsr160 ? ("[em]","enabled","[/em]") : "disabled");
}
if ($args->{verify}) {
if ($meta->initialized()) {
my $repositories = $args->{repository} ? [ $args->{repository} ] : $meta->get('repositories');
for my $repo (@$repositories) {
my $url = get_download_url($meta,$repo,$ret->{type},$ret->{version});
$logger->info("Checking against $repo");
verify_signature($file,$url);
}
} else {
$logger->error("Cannot verify signature since Jolokia META data couldn't be downloaded");
}
}
}
=head2 repack
Repack an Jolokia agent in order to switch on/off certain features.
=over
=item --policy / --no-policy
Adds a Jolokia policy file to the agent given as argument. By default a policy
file F<jolokia-access.xml> from the current directory is used, but this file
can be directly specified with the C<--policy-file> option. For example,
jolokia repack --policy jolokia.war
add the local policy file F<jolokia-access.xml> to the WAR agent specified as
argument. A sample F<jolokia-access.xml> can be downloaded with C<jolokia
--policy> which will then be saved locally. The policy contained in agent can
be viewed with C<jolokia --policy jolokia.war>. L<JMX::Jmx4Perl::Manual/"ACCESS
POLICY"> contains more information about Jolokia policy files.
=item --security / --no-security
For WAR agents, the included F<web.xml> descriptor can contain authentication
configuration. This configuration (which is absent by default), associates an
URL pattern with a role. With C<jolokia repack --security jolokia.war> the
authenticatin mechanism is switched on with an associated role "Jolokia". You
need to configure your servlet container accordingly to connect a user to this
role. The role can be specified with C<--security-role> (which implies
C<--security>):
jolokia repack --security-role JMX jolokia.war
=item --jsr160-proxy / --no-jsr160-proxy
By default, the WAR agent allows for JSR-160 proxy requests. This can be
switched by repacking the agent with C<--no-jsr160-proxy>:
jolokia repack --no-jsr160 jolokia.war
=back
=cut
sub command_repack {
my ($meta,$args,$file) = @_;
my $artifact_handler = new JMX::Jmx4Perl::Agent::Jolokia::ArtifactHandler(logger => $logger, meta => $meta,file => $file);
my $done = undef;
if ($args->{'policy-file'}) {
$artifact_handler->add_policy($args->{'policy-file'});
$done = 1;
} elsif (defined($args->{policy})) {
if ($args->{policy}) {
$artifact_handler->add_policy("jolokia-access.xml");
} else {
$artifact_handler->remove_policy;
}
$done = 1;
}
# Security handling
if (defined($args->{security}) || $args->{'security-role'}) {
fatal("--security can only be used with WAR agents") unless $artifact_handler->type eq "war";
my $webxml_handler = new JMX::Jmx4Perl::Agent::Jolokia::WebXmlHandler(logger => $logger);
my $webxml = $artifact_handler->extract_webxml();
my $new_webxml;
if ( (defined($args->{security}) && $args->{security}) || $args->{'security-role'} ) {
my $role = $args->{'security-role'} || "Jolokia";
$new_webxml = $webxml_handler->add_security($webxml,{ role => $role });
} else {
$new_webxml = $webxml_handler->remove_security($webxml);
}
$artifact_handler->update_webxml($new_webxml);
$done = 1;
}
# JSR-160 proxy
if (defined($args->{'jsr160-proxy'})) {
fatal("--jsr160-proxy can only be used with WAR agents") unless $artifact_handler->type eq "war";
my $webxml_handler = new JMX::Jmx4Perl::Agent::Jolokia::WebXmlHandler(logger => $logger);
my $webxml = $artifact_handler->extract_webxml();
my $new_webxml =
$args->{'jsr160-proxy'} ?
$webxml_handler->add_jsr160_proxy($webxml) :
$webxml_handler->remove_jsr160_proxy($webxml);
$artifact_handler->update_webxml($new_webxml) if $new_webxml;
$done = 1;
}
fatal("Nothing to repack (at least one of --policy/--policy-file/--security/--jsr160-proxy required)") unless $done;
}
# =======================================================================================
sub create_ua {
my $config = shift || {};
return new JMX::Jmx4Perl::Agent::Jolokia::DownloadAgent(quiet => $config->{quiet},%{$config->{ua_config}});
}
sub download {
my ($url, $file, $args) = @_;
my $config = $args || {};
my $ua = create_ua($args);
my $response = $ua->get($url,":content_file" => $file);
if ($response->is_error) {
fatal("Could not download agent from " . $url . ": " . $response->status_line);
}
$logger->info("Saved ", "[em]", $file, "[/em]");
}
sub verify_signature {
my $file = shift;
my $url = shift;
$verifier->verify(url => $url, path => $file);
}
sub verify_version {
my ($meta,$version) = @_;
my @versions = keys %{$meta->get('versions')};
$logger->error("No version $version known. Known versions: [",join(", ",sort @versions),"]") && die "\n"
unless grep { $version eq $_ } @versions;
$logger->warn("This Jmx4Perl version $JMX::Jmx4Perl::VERSION is not supported by Jolokia version $version")
unless $meta->versions_compatible($JMX::Jmx4Perl::VERSION,$version);
}
sub get_download_url {
my ($meta,$repository,$agent,$version) = @_;
my ($name,$artifact) = artifact_and_name($meta,$agent,$version);
$repository =~ s/\/+$//;
my $version_path = $version;
$version_path = $1 . "-SNAPSHOT" if $version =~ /(.*)-\d+\.\d+-\d+/;
return $repository . "/org/jolokia/" . $name . "/" . $version_path . "/" . $artifact;
}
sub get_snapshot_version {
my ($meta,$repository,$agent,$version,$args) = @_;
my ($name,$artifact) = artifact_and_name($meta,$agent,$version);
my $meta_url = $repository . "/org/jolokia/" . $name . "/" . $version . "/maven-metadata.xml";
my $ua = create_ua($args);
my $response = $ua->get($meta_url);
if ($response->is_error) {
fatal("Could not download maven meta from " . $meta_url . " for getting snapshot version: " . $response->status_line);
}
my $content = $response->decoded_content;
my $timestamp = $1 if $content =~ m|<timestamp>\s*(.*?)\s*</timestamp>|si;
my $build_nr = $1 if $content =~ m|<buildNumber>\s*(.*?)\s*</buildNumber>|si;
my $base_version = $1 if $version =~ /(.*)-SNAPSHOT$/;
fatal("Couldn't parse timestamp or buildNumber from $meta_url") unless defined($timestamp) && defined($build_nr);
return $base_version . "-" . $timestamp . "-" . $build_nr;
}
# Map agent to its artifact id and its full name (including any classifier)
sub artifact_and_name {
my $meta = shift;
my $agent = shift;
my $version = shift;
my $mapping = $meta->get("mapping");
my $parts = $mapping->{$agent}
|| $logger->error("Unknown agent type $agent. Known agent types are: ",join(", ",sort keys %$mapping)) && exit(1);
my $name = $parts->[0];
my $artifact = $parts->[1];
$artifact =~ s/\%v/$version/g;
return ($name,$artifact);
}
sub fatal {
$logger->error(@_);
die "\n";
}
=head1 SEE ALSO
L<check_jmx4perl> - a production ready Nagios check using L<JMX::Jmx4Perl>
L<jmx4perl> - CLI for accessing the agents
L<j4psh> - readline based JMX shell with context sensitive command line
completion.
=head1 LICENSE
This file is part of jmx4perl.
Jmx4perl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
jmx4perl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jmx4perl. If not, see <http://www.gnu.org/licenses/>.
=head1 AUTHOR
roland@cpan.org
=cut