mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-11 13:40:07 +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,
|
||||
);
|
||||
|
||||
has 'run_once_on_start' => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
required => 0,
|
||||
default => sub { return 0 },
|
||||
);
|
||||
|
||||
has 'links' => (
|
||||
is => 'rw',
|
||||
isa => 'Maybe[HashRef]',
|
||||
@@ -4675,7 +4682,7 @@ sub main {
|
||||
$o->get_opts();
|
||||
|
||||
my $dp = $o->DSNParser();
|
||||
$dp->prop('set-vars', $o->get('set-vars'));
|
||||
$dp->prop('set-vars', $o->set_vars());
|
||||
|
||||
if ( !$o->get('help') ) {
|
||||
}
|
||||
@@ -4725,6 +4732,7 @@ sub main {
|
||||
api_key => $api_key,
|
||||
lib_dir => $o->get('lib'),
|
||||
Cxn => $cxn,
|
||||
agent_uuid => $o->get('agent-uuid'), # optional
|
||||
);
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
@@ -4767,6 +4775,14 @@ sub main {
|
||||
$daemon = new Daemon(o=>$o);
|
||||
$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.
|
||||
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.
|
||||
# Use the tool's built-in default until a config is gotten,
|
||||
# then config->{check-interval} will be pass in.
|
||||
@@ -4844,6 +4853,9 @@ sub connect_to_percona {
|
||||
my $lib_dir = $args{lib_dir};
|
||||
my $cxn = $args{Cxn};
|
||||
|
||||
# Optional args
|
||||
my $agent_uuid = $args{agent_uuid};
|
||||
|
||||
# During initial connection and agent init, wait less time
|
||||
# than --check-interval between errors.
|
||||
# TODO: make user-configurable? --reconnect-interval?
|
||||
@@ -4870,6 +4882,7 @@ sub connect_to_percona {
|
||||
lib_dir => $lib_dir,
|
||||
agents_link => $entry_links->{agents},
|
||||
Cxn => $cxn,
|
||||
agent_uuid => $agent_uuid,
|
||||
);
|
||||
|
||||
return $client, $agent;
|
||||
@@ -4935,6 +4948,7 @@ sub init_agent {
|
||||
# Optional args
|
||||
my $versions = $args{versions};
|
||||
my $_oktorun = $args{oktorun} || sub { return $oktorun };
|
||||
my $agent_uuid = $args{agent_uuid};
|
||||
|
||||
_info('Initializing agent');
|
||||
|
||||
@@ -4963,7 +4977,18 @@ sub init_agent {
|
||||
my $agent;
|
||||
my $action;
|
||||
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");
|
||||
my $agent_hashref = decode_json(slurp($agent_file));
|
||||
$agent = Percona::WebAPI::Resource::Agent->new(%$agent_hashref);
|
||||
@@ -5007,20 +5032,10 @@ sub init_agent {
|
||||
if ( !$agent_uri ) {
|
||||
_err("No URI for Agent " . $agent->name);
|
||||
}
|
||||
# TODO: eval
|
||||
$agent = $client->get(
|
||||
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");
|
||||
return $agent;
|
||||
@@ -5051,11 +5066,62 @@ sub run_agent {
|
||||
|
||||
_info('Running agent ' . $agent->name);
|
||||
|
||||
my $success;
|
||||
my $config;
|
||||
my $services;
|
||||
AGENT_LOOP:
|
||||
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');
|
||||
my $new_config = eval {
|
||||
$client->get(
|
||||
@@ -5082,6 +5148,8 @@ sub run_agent {
|
||||
}
|
||||
else {
|
||||
eval {
|
||||
_info("Running config: " . ($config ? $config->ts : ''));
|
||||
_info("Current config: " . $new_config->ts);
|
||||
if ( !$config || $new_config->ts > $config->ts ) {
|
||||
$lib_dir = apply_config(
|
||||
agent => $agent,
|
||||
@@ -5089,6 +5157,7 @@ sub run_agent {
|
||||
lib_dir => $lib_dir,
|
||||
);
|
||||
$config = $new_config;
|
||||
$success = 1;
|
||||
_info('Config ' . $config->ts . ' applied successfully');
|
||||
}
|
||||
else {
|
||||
@@ -5102,9 +5171,26 @@ sub run_agent {
|
||||
}
|
||||
}
|
||||
|
||||
# Get services only if there's a current, running config.
|
||||
# Without one, we won't know how to implement services.
|
||||
if ( $config && $config->links->{services} ) {
|
||||
return ($config, $success);
|
||||
}
|
||||
|
||||
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 {
|
||||
_info('Getting services');
|
||||
|
||||
@@ -5130,6 +5216,8 @@ sub run_agent {
|
||||
);
|
||||
|
||||
$services = $new_services;
|
||||
$success = 1;
|
||||
|
||||
_info('Services updated successfully: '
|
||||
. join(', ', map { $_->name } @$services));
|
||||
}
|
||||
@@ -5140,17 +5228,8 @@ sub run_agent {
|
||||
if ( $EVAL_ERROR ) {
|
||||
_warn($EVAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
# 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;
|
||||
return ($services, $success);
|
||||
}
|
||||
|
||||
# Write a Config resource to a Percona Toolkit config file,
|
||||
@@ -5188,6 +5267,8 @@ sub write_config {
|
||||
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 {
|
||||
my (%args) = @_;
|
||||
|
||||
@@ -5196,7 +5277,11 @@ sub init_lib_dir {
|
||||
)) or die;
|
||||
my $lib_dir = $args{lib_dir};
|
||||
|
||||
_info("Initializing --lib $lib_dir");
|
||||
|
||||
eval {
|
||||
if ( ! -d $lib_dir ) {
|
||||
_info("$lib_dir does not exist, creating");
|
||||
mkdir $lib_dir or die "Cannot mkdir $lib_dir: $OS_ERROR";
|
||||
}
|
||||
elsif ( ! -w $lib_dir ) {
|
||||
@@ -5210,6 +5295,10 @@ sub init_lib_dir {
|
||||
elsif ( ! -w $services_dir ) {
|
||||
die "$services_dir is not writable.\n";
|
||||
}
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
_warn("Error initializing --lib $lib_dir: $EVAL_ERROR");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -6001,6 +6090,12 @@ L<"--run-service"> and L<"--send-data"> are mutually exclusive.
|
||||
|
||||
=over
|
||||
|
||||
=item --agent-uuid
|
||||
|
||||
type: string
|
||||
|
||||
Existing agent UUID for re-installing an agent.
|
||||
|
||||
=item --api-key
|
||||
|
||||
type: string
|
||||
|
@@ -46,6 +46,13 @@ has 'spool_schedule' => (
|
||||
required => 0,
|
||||
);
|
||||
|
||||
has 'run_once_on_start' => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
required => 0,
|
||||
default => sub { return 0 },
|
||||
);
|
||||
|
||||
has 'links' => (
|
||||
is => 'rw',
|
||||
isa => 'Maybe[HashRef]',
|
||||
|
Reference in New Issue
Block a user