mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-11 21:51:21 +00:00
Add Service.run_once_on_start. Refactor get config and get services blocks.
This commit is contained in:
161
bin/pt-agent
161
bin/pt-agent
@@ -1362,6 +1362,13 @@ has 'spool_schedule' => (
|
|||||||
required => 0,
|
required => 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
has 'run_once_on_start' => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
required => 0,
|
||||||
|
default => sub { return 0 },
|
||||||
|
);
|
||||||
|
|
||||||
has 'links' => (
|
has 'links' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'Maybe[HashRef]',
|
isa => 'Maybe[HashRef]',
|
||||||
@@ -4675,7 +4682,7 @@ sub main {
|
|||||||
$o->get_opts();
|
$o->get_opts();
|
||||||
|
|
||||||
my $dp = $o->DSNParser();
|
my $dp = $o->DSNParser();
|
||||||
$dp->prop('set-vars', $o->get('set-vars'));
|
$dp->prop('set-vars', $o->set_vars());
|
||||||
|
|
||||||
if ( !$o->get('help') ) {
|
if ( !$o->get('help') ) {
|
||||||
}
|
}
|
||||||
@@ -4725,6 +4732,7 @@ sub main {
|
|||||||
api_key => $api_key,
|
api_key => $api_key,
|
||||||
lib_dir => $o->get('lib'),
|
lib_dir => $o->get('lib'),
|
||||||
Cxn => $cxn,
|
Cxn => $cxn,
|
||||||
|
agent_uuid => $o->get('agent-uuid'), # optional
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
if ( $EVAL_ERROR ) {
|
if ( $EVAL_ERROR ) {
|
||||||
@@ -4767,6 +4775,14 @@ sub main {
|
|||||||
$daemon = new Daemon(o=>$o);
|
$daemon = new Daemon(o=>$o);
|
||||||
$daemon->make_PID_file();
|
$daemon->make_PID_file();
|
||||||
}
|
}
|
||||||
|
# If we daemonized, the parent has already exited and we're the child.
|
||||||
|
# We shared a copy of every Cxn with the parent, and the parent's copies
|
||||||
|
# were destroyed but the dbhs were not disconnected because the parent
|
||||||
|
# attrib was true. Now, as the child, set it false so the dbhs will be
|
||||||
|
# disconnected when our Cxn copies are destroyed. If we didn't daemonize,
|
||||||
|
# then we're not really a parent (since we have no children), so set it
|
||||||
|
# false to auto-disconnect the dbhs when our Cxns are destroyed.
|
||||||
|
$cxn->{parent} = 0;
|
||||||
|
|
||||||
# Check and init the config file.
|
# Check and init the config file.
|
||||||
my $config_file = get_config_file();
|
my $config_file = get_config_file();
|
||||||
@@ -4789,13 +4805,6 @@ sub main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check and init the --lib dir. This dir is used to save
|
|
||||||
# the Agent resource (/agent), Service resources (/services/),
|
|
||||||
# and crontab for services (/conrtab, /crontab.err).
|
|
||||||
init_lib_dir(
|
|
||||||
lib_dir => $o->get('lib'),
|
|
||||||
);
|
|
||||||
|
|
||||||
# Wait time between checking for new config and services.
|
# Wait time between checking for new config and services.
|
||||||
# Use the tool's built-in default until a config is gotten,
|
# Use the tool's built-in default until a config is gotten,
|
||||||
# then config->{check-interval} will be pass in.
|
# then config->{check-interval} will be pass in.
|
||||||
@@ -4844,6 +4853,9 @@ sub connect_to_percona {
|
|||||||
my $lib_dir = $args{lib_dir};
|
my $lib_dir = $args{lib_dir};
|
||||||
my $cxn = $args{Cxn};
|
my $cxn = $args{Cxn};
|
||||||
|
|
||||||
|
# Optional args
|
||||||
|
my $agent_uuid = $args{agent_uuid};
|
||||||
|
|
||||||
# During initial connection and agent init, wait less time
|
# During initial connection and agent init, wait less time
|
||||||
# than --check-interval between errors.
|
# than --check-interval between errors.
|
||||||
# TODO: make user-configurable? --reconnect-interval?
|
# TODO: make user-configurable? --reconnect-interval?
|
||||||
@@ -4870,6 +4882,7 @@ sub connect_to_percona {
|
|||||||
lib_dir => $lib_dir,
|
lib_dir => $lib_dir,
|
||||||
agents_link => $entry_links->{agents},
|
agents_link => $entry_links->{agents},
|
||||||
Cxn => $cxn,
|
Cxn => $cxn,
|
||||||
|
agent_uuid => $agent_uuid,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $client, $agent;
|
return $client, $agent;
|
||||||
@@ -4935,6 +4948,7 @@ sub init_agent {
|
|||||||
# Optional args
|
# Optional args
|
||||||
my $versions = $args{versions};
|
my $versions = $args{versions};
|
||||||
my $_oktorun = $args{oktorun} || sub { return $oktorun };
|
my $_oktorun = $args{oktorun} || sub { return $oktorun };
|
||||||
|
my $agent_uuid = $args{agent_uuid};
|
||||||
|
|
||||||
_info('Initializing agent');
|
_info('Initializing agent');
|
||||||
|
|
||||||
@@ -4963,7 +4977,18 @@ sub init_agent {
|
|||||||
my $agent;
|
my $agent;
|
||||||
my $action;
|
my $action;
|
||||||
my $link;
|
my $link;
|
||||||
if ( -f $agent_file ) {
|
if ( $agent_uuid ) {
|
||||||
|
_info("Re-creating Agent with UUID $agent_uuid");
|
||||||
|
chomp(my $hostname = `hostname`);
|
||||||
|
$agent = Percona::WebAPI::Resource::Agent->new(
|
||||||
|
uuid => $agent_uuid,
|
||||||
|
hostname => $hostname,
|
||||||
|
versions => $versions,
|
||||||
|
);
|
||||||
|
$action = 'put'; # must be lc
|
||||||
|
$link = $agents_link . '/' . $agent_uuid;
|
||||||
|
}
|
||||||
|
elsif ( -f $agent_file ) {
|
||||||
_info("Reading saved Agent from $agent_file");
|
_info("Reading saved Agent from $agent_file");
|
||||||
my $agent_hashref = decode_json(slurp($agent_file));
|
my $agent_hashref = decode_json(slurp($agent_file));
|
||||||
$agent = Percona::WebAPI::Resource::Agent->new(%$agent_hashref);
|
$agent = Percona::WebAPI::Resource::Agent->new(%$agent_hashref);
|
||||||
@@ -5007,20 +5032,10 @@ sub init_agent {
|
|||||||
if ( !$agent_uri ) {
|
if ( !$agent_uri ) {
|
||||||
_err("No URI for Agent " . $agent->name);
|
_err("No URI for Agent " . $agent->name);
|
||||||
}
|
}
|
||||||
|
# TODO: eval
|
||||||
$agent = $client->get(
|
$agent = $client->get(
|
||||||
link => $agent_uri,
|
link => $agent_uri,
|
||||||
);
|
);
|
||||||
eval {
|
|
||||||
save_agent(
|
|
||||||
agent => $agent,
|
|
||||||
lib_dir => $lib_dir,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
if ( $EVAL_ERROR ) {
|
|
||||||
_warn("Error saving Agent to $agent_file: $EVAL_ERROR\n"
|
|
||||||
. "pt-agent will continue running and try to save "
|
|
||||||
. "the Agent later.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_info("Agent " . $agent->name . " initialized and ready");
|
_info("Agent " . $agent->name . " initialized and ready");
|
||||||
return $agent;
|
return $agent;
|
||||||
@@ -5051,11 +5066,62 @@ sub run_agent {
|
|||||||
|
|
||||||
_info('Running agent ' . $agent->name);
|
_info('Running agent ' . $agent->name);
|
||||||
|
|
||||||
|
my $success;
|
||||||
my $config;
|
my $config;
|
||||||
my $services;
|
my $services;
|
||||||
AGENT_LOOP:
|
AGENT_LOOP:
|
||||||
while ( $oktorun->() ) {
|
while ( $oktorun->() ) {
|
||||||
|
|
||||||
|
($config, $success) = get_config(
|
||||||
|
agent => $agent,
|
||||||
|
client => $client,
|
||||||
|
lib_dir => $lib_dir,
|
||||||
|
config => $config,
|
||||||
|
services => $services,
|
||||||
|
);
|
||||||
|
|
||||||
|
# Get services only if we successfully got the config because the services
|
||||||
|
# may depened on the current config, specifically the --spool dir.
|
||||||
|
if ( $success && $config && $config->links->{services} ) {
|
||||||
|
($services, $success) = get_services(
|
||||||
|
agent => $agent,
|
||||||
|
client => $client,
|
||||||
|
lib_dir => $lib_dir,
|
||||||
|
config => $config,
|
||||||
|
services => $services,
|
||||||
|
json => $args{json}, # optional, for testing
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no config yet, the tool's built-in default for
|
||||||
|
# --check-interval is used instead.
|
||||||
|
$interval->($config ? $config->options->{'check-interval'} : ());
|
||||||
|
|
||||||
|
} # AGENT_LOOP
|
||||||
|
|
||||||
|
# This shouldn't happen until the service is stopped/killed.
|
||||||
|
_info('Agent ' . $agent->name . ' has stopped');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_config {
|
||||||
|
my (%args) = @_;
|
||||||
|
have_required_args(\%args, qw(
|
||||||
|
agent
|
||||||
|
client
|
||||||
|
lib_dir
|
||||||
|
)) or die;
|
||||||
|
my $agent = $args{agent};
|
||||||
|
my $client = $args{client};
|
||||||
|
my $lib_dir = $args{lib_dir};
|
||||||
|
|
||||||
|
# Optional args
|
||||||
|
my $config = $args{config}; # may not be defined yet
|
||||||
|
my $services = $args{services}; # may not be defined yet
|
||||||
|
|
||||||
|
my $success = 0;
|
||||||
|
|
||||||
_info('Getting config');
|
_info('Getting config');
|
||||||
my $new_config = eval {
|
my $new_config = eval {
|
||||||
$client->get(
|
$client->get(
|
||||||
@@ -5082,6 +5148,8 @@ sub run_agent {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eval {
|
eval {
|
||||||
|
_info("Running config: " . ($config ? $config->ts : ''));
|
||||||
|
_info("Current config: " . $new_config->ts);
|
||||||
if ( !$config || $new_config->ts > $config->ts ) {
|
if ( !$config || $new_config->ts > $config->ts ) {
|
||||||
$lib_dir = apply_config(
|
$lib_dir = apply_config(
|
||||||
agent => $agent,
|
agent => $agent,
|
||||||
@@ -5089,6 +5157,7 @@ sub run_agent {
|
|||||||
lib_dir => $lib_dir,
|
lib_dir => $lib_dir,
|
||||||
);
|
);
|
||||||
$config = $new_config;
|
$config = $new_config;
|
||||||
|
$success = 1;
|
||||||
_info('Config ' . $config->ts . ' applied successfully');
|
_info('Config ' . $config->ts . ' applied successfully');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -5102,9 +5171,26 @@ sub run_agent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get services only if there's a current, running config.
|
return ($config, $success);
|
||||||
# Without one, we won't know how to implement services.
|
}
|
||||||
if ( $config && $config->links->{services} ) {
|
|
||||||
|
sub get_services {
|
||||||
|
my (%args) = @_;
|
||||||
|
have_required_args(\%args, qw(
|
||||||
|
agent
|
||||||
|
client
|
||||||
|
lib_dir
|
||||||
|
)) or die;
|
||||||
|
my $agent = $args{agent};
|
||||||
|
my $client = $args{client};
|
||||||
|
my $lib_dir = $args{lib_dir};
|
||||||
|
|
||||||
|
# Optional args
|
||||||
|
my $config = $args{config}; # may not be defined yet
|
||||||
|
my $services = $args{services}; # may not be defined yet
|
||||||
|
|
||||||
|
my $success = 0;
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
_info('Getting services');
|
_info('Getting services');
|
||||||
|
|
||||||
@@ -5130,6 +5216,8 @@ sub run_agent {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$services = $new_services;
|
$services = $new_services;
|
||||||
|
$success = 1;
|
||||||
|
|
||||||
_info('Services updated successfully: '
|
_info('Services updated successfully: '
|
||||||
. join(', ', map { $_->name } @$services));
|
. join(', ', map { $_->name } @$services));
|
||||||
}
|
}
|
||||||
@@ -5140,17 +5228,8 @@ sub run_agent {
|
|||||||
if ( $EVAL_ERROR ) {
|
if ( $EVAL_ERROR ) {
|
||||||
_warn($EVAL_ERROR);
|
_warn($EVAL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
# If no config yet, the tool's built-in default for
|
return ($services, $success);
|
||||||
# --check-interval is used instead.
|
|
||||||
$interval->($config ? $config->options->{'check-interval'} : ());
|
|
||||||
|
|
||||||
} # AGENT_LOOP
|
|
||||||
|
|
||||||
# This shouldn't happen until the service is stopped/killed.
|
|
||||||
_info('Agent ' . $agent->name . ' has stopped');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Write a Config resource to a Percona Toolkit config file,
|
# Write a Config resource to a Percona Toolkit config file,
|
||||||
@@ -5188,6 +5267,8 @@ sub write_config {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check and init the --lib dir. This dir is used to save the Agent resource (/agent),
|
||||||
|
# Service resources (/services/), and crontab for services (/conrtab, /crontab.err).
|
||||||
sub init_lib_dir {
|
sub init_lib_dir {
|
||||||
my (%args) = @_;
|
my (%args) = @_;
|
||||||
|
|
||||||
@@ -5196,7 +5277,11 @@ sub init_lib_dir {
|
|||||||
)) or die;
|
)) or die;
|
||||||
my $lib_dir = $args{lib_dir};
|
my $lib_dir = $args{lib_dir};
|
||||||
|
|
||||||
|
_info("Initializing --lib $lib_dir");
|
||||||
|
|
||||||
|
eval {
|
||||||
if ( ! -d $lib_dir ) {
|
if ( ! -d $lib_dir ) {
|
||||||
|
_info("$lib_dir does not exist, creating");
|
||||||
mkdir $lib_dir or die "Cannot mkdir $lib_dir: $OS_ERROR";
|
mkdir $lib_dir or die "Cannot mkdir $lib_dir: $OS_ERROR";
|
||||||
}
|
}
|
||||||
elsif ( ! -w $lib_dir ) {
|
elsif ( ! -w $lib_dir ) {
|
||||||
@@ -5210,6 +5295,10 @@ sub init_lib_dir {
|
|||||||
elsif ( ! -w $services_dir ) {
|
elsif ( ! -w $services_dir ) {
|
||||||
die "$services_dir is not writable.\n";
|
die "$services_dir is not writable.\n";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if ( $EVAL_ERROR ) {
|
||||||
|
_warn("Error initializing --lib $lib_dir: $EVAL_ERROR");
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -6001,6 +6090,12 @@ L<"--run-service"> and L<"--send-data"> are mutually exclusive.
|
|||||||
|
|
||||||
=over
|
=over
|
||||||
|
|
||||||
|
=item --agent-uuid
|
||||||
|
|
||||||
|
type: string
|
||||||
|
|
||||||
|
Existing agent UUID for re-installing an agent.
|
||||||
|
|
||||||
=item --api-key
|
=item --api-key
|
||||||
|
|
||||||
type: string
|
type: string
|
||||||
|
@@ -46,6 +46,13 @@ has 'spool_schedule' => (
|
|||||||
required => 0,
|
required => 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
has 'run_once_on_start' => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
required => 0,
|
||||||
|
default => sub { return 0 },
|
||||||
|
);
|
||||||
|
|
||||||
has 'links' => (
|
has 'links' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'Maybe[HashRef]',
|
isa => 'Maybe[HashRef]',
|
||||||
|
Reference in New Issue
Block a user