mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-12-24 02:01:42 +08:00
Get and send real program version when the agent starts.
This commit is contained in:
137
bin/pt-agent
137
bin/pt-agent
@@ -4679,8 +4679,6 @@ sub main {
|
||||
|
||||
if ( !$o->get('help') ) {
|
||||
}
|
||||
|
||||
#Pingback::validate_options($o);
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
@@ -4694,16 +4692,20 @@ sub main {
|
||||
. "in a --config file or specify it with --api-key.");
|
||||
}
|
||||
|
||||
# ########################################################################
|
||||
# Connect to MysSQL.
|
||||
# ########################################################################
|
||||
my $cxn = Cxn->new(
|
||||
dsn_string => '',
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
);
|
||||
|
||||
# ########################################################################
|
||||
# --run-service
|
||||
# This runs locally and offline, doesn't need a web API connection.
|
||||
# ########################################################################
|
||||
if ( my $service = $o->get('run-service') ) {
|
||||
my $cxn = Cxn->new(
|
||||
dsn_string => '',
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
);
|
||||
$exit_status = run_service(
|
||||
service => $service,
|
||||
spool_dir => $o->get('spool'),
|
||||
@@ -4714,28 +4716,15 @@ sub main {
|
||||
exit $exit_status;
|
||||
}
|
||||
|
||||
# ########################################################################
|
||||
# Daemonize first so all output goes to the --log.
|
||||
# ########################################################################
|
||||
my $daemon;
|
||||
if ( $o->get('daemonize') ) {
|
||||
$daemon = new Daemon(o=>$o);
|
||||
$daemon->daemonize();
|
||||
PTDEBUG && _d('I am a daemon now');
|
||||
}
|
||||
elsif ( $o->get('pid') ) {
|
||||
$daemon = new Daemon(o=>$o);
|
||||
$daemon->make_PID_file();
|
||||
}
|
||||
|
||||
# ########################################################################
|
||||
# Connect to the Percona web API.
|
||||
# ########################################################################
|
||||
my ($client, $agent);
|
||||
eval {
|
||||
($client, $agent) = connect_to_percona(
|
||||
api_key => $api_key,
|
||||
api_key => $api_key,
|
||||
lib_dir => $o->get('lib'),
|
||||
Cxn => $cxn,
|
||||
);
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
@@ -4766,6 +4755,18 @@ sub main {
|
||||
# external errors, like Percona web API not responding, should be
|
||||
# retried forever.
|
||||
# ########################################################################
|
||||
|
||||
# Daemonize first so all output goes to the --log.
|
||||
my $daemon;
|
||||
if ( $o->get('daemonize') ) {
|
||||
$daemon = new Daemon(o=>$o);
|
||||
$daemon->daemonize();
|
||||
PTDEBUG && _d('I am a daemon now');
|
||||
}
|
||||
elsif ( $o->get('pid') ) {
|
||||
$daemon = new Daemon(o=>$o);
|
||||
$daemon->make_PID_file();
|
||||
}
|
||||
|
||||
# Check and init the config file.
|
||||
my $config_file = get_config_file();
|
||||
@@ -4837,9 +4838,11 @@ sub connect_to_percona {
|
||||
have_required_args(\%args, qw(
|
||||
api_key
|
||||
lib_dir
|
||||
Cxn
|
||||
)) or die;
|
||||
my $api_key = $args{api_key};
|
||||
my $lib_dir = $args{lib_dir};
|
||||
my $cxn = $args{Cxn};
|
||||
|
||||
# During initial connection and agent init, wait less time
|
||||
# than --check-interval between errors.
|
||||
@@ -4866,6 +4869,7 @@ sub connect_to_percona {
|
||||
interval => $init_wait,
|
||||
lib_dir => $lib_dir,
|
||||
agents_link => $entry_links->{agents},
|
||||
Cxn => $cxn,
|
||||
);
|
||||
|
||||
return $client, $agent;
|
||||
@@ -4920,11 +4924,13 @@ sub init_agent {
|
||||
interval
|
||||
lib_dir
|
||||
agents_link
|
||||
Cxn
|
||||
)) or die;
|
||||
my $client = $args{client};
|
||||
my $interval = $args{interval};
|
||||
my $lib_dir = $args{lib_dir};
|
||||
my $agents_link = $args{agents_link};
|
||||
my $cxn = $args{Cxn};
|
||||
|
||||
# Optional args
|
||||
my $versions = $args{versions};
|
||||
@@ -4934,7 +4940,22 @@ sub init_agent {
|
||||
|
||||
# Do a version-check every time the agent starts. If versions
|
||||
# have changed, this can affect how services are implemented.
|
||||
$versions ||= get_versions();
|
||||
if ( !$versions ) {
|
||||
TRY:
|
||||
for ( 1..3 ) {
|
||||
eval {
|
||||
$cxn->connect();
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
_warn("Cannot connect to MySQL: $EVAL_ERROR");
|
||||
$interval->();
|
||||
next TRY;
|
||||
}
|
||||
$versions = get_versions(dbh => $cxn->dbh, dsn => $cxn->dsn);
|
||||
$cxn->dbh->disconnect();
|
||||
last TRY;
|
||||
}
|
||||
}
|
||||
|
||||
# If there's a saved agent, then this is an existing agent being
|
||||
# restarted. Else this is a new agent.
|
||||
@@ -5387,13 +5408,19 @@ sub run_service {
|
||||
# Take a quick look through all the tasks to see if any
|
||||
# will require a MySQL connection. If so, connect now.
|
||||
if ( grep { $_->query } @$tasks ) {
|
||||
eval {
|
||||
$cxn->connect();
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
_warn("Cannot connect to MySQL: $EVAL_ERROR");
|
||||
return 1;
|
||||
TRY:
|
||||
for ( 1..3 ) {
|
||||
eval {
|
||||
$cxn->connect();
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
_warn("Cannot connect to MySQL: $EVAL_ERROR");
|
||||
sleep(5);
|
||||
next TRY;
|
||||
}
|
||||
last TRY;
|
||||
}
|
||||
return 1 unless $cxn->dbh;
|
||||
}
|
||||
|
||||
my @output_files;
|
||||
@@ -5760,12 +5787,54 @@ sub _err {
|
||||
exit $exit_status;
|
||||
}
|
||||
|
||||
# TODO: use VersionCheck::get_versions().
|
||||
sub get_versions {
|
||||
return {
|
||||
'Perl' => sprintf('%vd', $PERL_VERSION),
|
||||
'Percona::WebAPI::Client' => "$Percona::WebAPI::Client::VERSION",
|
||||
};
|
||||
my (%args) = @_;
|
||||
my $dbh = $args{dbh};
|
||||
my $dsn = $args{dsn};
|
||||
|
||||
# This is currently the actual response from GET v.percona.com
|
||||
my $fake_response = <<EOL;
|
||||
OS;os_version
|
||||
MySQL;mysql_variable;version_comment,version
|
||||
Perl;perl_version
|
||||
DBD::mysql;perl_module_version
|
||||
Percona::Toolkit;perl_module_version
|
||||
EOL
|
||||
|
||||
my $items = VersionCheck::parse_server_response(
|
||||
response => $fake_response,
|
||||
);
|
||||
|
||||
my ($name, $id) = VersionCheck::get_instance_id(
|
||||
{ dbh => $dbh, dsn => $dsn },
|
||||
);
|
||||
|
||||
my $instances = [
|
||||
{ name => $name, id => $id, dbh => $dbh, dsn => $dsn },
|
||||
{ name => 'system', id => 0, },
|
||||
];
|
||||
|
||||
my $versions = VersionCheck::get_versions(
|
||||
items => $items,
|
||||
instances => $instances,
|
||||
);
|
||||
|
||||
my %version_for;
|
||||
foreach my $item ( sort keys %$items ) {
|
||||
next unless exists $versions->{$item};
|
||||
if ( ref($versions->{$item}) eq 'HASH' ) {
|
||||
my $mysql_versions = $versions->{$item};
|
||||
for my $id ( sort keys %$mysql_versions ) {
|
||||
$version_for{$item} = $mysql_versions->{$id};
|
||||
}
|
||||
}
|
||||
else {
|
||||
$version_for{$item} = $versions->{$item};
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('Versions:', Dumper(\%version_for));
|
||||
return \%version_for;
|
||||
}
|
||||
|
||||
# Catches signals so we can exit gracefully.
|
||||
|
||||
@@ -23,9 +23,10 @@ package Percona::Test::Mock::UserAgent;
|
||||
sub new {
|
||||
my ($class, %args) = @_;
|
||||
my $self = {
|
||||
encode => $args{encode} || sub { return $_[0] },
|
||||
decode => $args{decode} || sub { return $_[0] },
|
||||
requests => [],
|
||||
encode => $args{encode} || sub { return $_[0] },
|
||||
decode => $args{decode} || sub { return $_[0] },
|
||||
requests => [],
|
||||
request_objs => [],
|
||||
responses => {
|
||||
get => [],
|
||||
post => [],
|
||||
@@ -35,14 +36,16 @@ sub new {
|
||||
post => [],
|
||||
put => [],
|
||||
},
|
||||
last_request => undef,
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub request {
|
||||
my ($self, $req) = @_;
|
||||
$self->{last_request} = $req;
|
||||
if ( scalar @{$self->{request_objs}} > 10 ) {
|
||||
$self->{request_objs} = [];
|
||||
}
|
||||
push @{$self->{request_objs}}, $req;
|
||||
my $type = lc($req->method);
|
||||
push @{$self->{requests}}, uc($type) . ' ' . $req->uri;
|
||||
if ( $type eq 'post' || $type eq 'put' ) {
|
||||
|
||||
@@ -33,8 +33,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0;
|
||||
|
||||
use Percona::Toolkit;
|
||||
|
||||
use Carp qw(croak);
|
||||
|
||||
use Test::More;
|
||||
|
||||
@@ -13,10 +13,24 @@ use Test::More;
|
||||
use JSON;
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
use Percona::Test;
|
||||
use PerconaTest;
|
||||
use Sandbox;
|
||||
use Percona::Test::Mock::UserAgent;
|
||||
require "$trunk/bin/pt-agent";
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $dbh = $sb->get_dbh_for('master');
|
||||
my $dsn = $sb->dsn_for('master');
|
||||
my $o = new OptionParser();
|
||||
$o->get_specs("$trunk/bin/pt-agent");
|
||||
$o->get_opts();
|
||||
my $cxn = Cxn->new(
|
||||
dsn_string => $dsn,
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
);
|
||||
|
||||
Percona::Toolkit->import(qw(Dumper));
|
||||
Percona::WebAPI::Representation->import(qw(as_hashref));
|
||||
|
||||
@@ -47,8 +61,6 @@ my $return_agent = {
|
||||
uuid => '123',
|
||||
hostname => `hostname`,
|
||||
versions => {
|
||||
'Percona::WebAPI::Client' => "$Percona::WebAPI::Client::VERSION",
|
||||
'Perl' => sprintf('%vd', $PERL_VERSION),
|
||||
},
|
||||
links => {
|
||||
self => '/agents/123',
|
||||
@@ -86,6 +98,7 @@ my $output = output(
|
||||
interval => $interval,
|
||||
agents_link => "/agents",
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -118,6 +131,21 @@ like(
|
||||
"Saved new Agent"
|
||||
) or diag($output);
|
||||
|
||||
my $sent_versions = decode_json($ua->{request_objs}->[0]->content);
|
||||
my $os = VersionCheck::get_os_version();
|
||||
|
||||
is(
|
||||
$sent_versions->{versions}->{OS} || '',
|
||||
$os,
|
||||
"Sent OS version"
|
||||
) or diag(Dumper($sent_versions));
|
||||
|
||||
like(
|
||||
$sent_versions->{versions}->{MySQL} || '',
|
||||
qr/$sandbox_version/,
|
||||
"Sent MySQL version"
|
||||
) or diag(Dumper($sent_versions));
|
||||
|
||||
# Repeat this test but this time fake an error, so the tool isn't
|
||||
# able to create the Agent first time, so it should wait (call
|
||||
# interval), and try again.
|
||||
@@ -158,6 +186,7 @@ $output = output(
|
||||
interval => $interval,
|
||||
agents_link => '/agents',
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -242,6 +271,7 @@ $output = output(
|
||||
interval => $interval,
|
||||
agents_link => '/agents',
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -277,4 +307,5 @@ is_deeply(
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
||||
|
||||
@@ -139,7 +139,7 @@ ok(
|
||||
);
|
||||
|
||||
is(
|
||||
$ua->{last_request}->header('content-type'),
|
||||
$ua->{request_objs}->[-1]->header('content-type'),
|
||||
'multipart/form-data; boundary=Ym91bmRhcnk',
|
||||
'Content-Type=multipart/form-data; boundary=Ym91bmRhcnk'
|
||||
) or diag(Dumper($ua));
|
||||
|
||||
Reference in New Issue
Block a user