Add Service.run_once_on_start. Refactor get config and get services blocks.

This commit is contained in:
Daniel Nichter
2013-03-22 12:08:45 -06:00
parent c1cce0c6ca
commit 9e1d935e19
2 changed files with 222 additions and 120 deletions

View File

@@ -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

View File

@@ -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]',