Imported Upstream version 1.12
This commit is contained in:
110
scripts/cacti_jmx4perl
Executable file
110
scripts/cacti_jmx4perl
Executable 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
1911
scripts/check_jmx4perl
Executable file
File diff suppressed because it is too large
Load Diff
144
scripts/j4psh
Executable file
144
scripts/j4psh
Executable 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
779
scripts/jmx4perl
Executable 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
647
scripts/jolokia
Executable 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
|
||||
Reference in New Issue
Block a user