mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 21:19:59 +00:00
Change start_services() to run_services() and make it do triple duty: start, restart, and stop. When a real service is removed, call its stop- meta-service before write_services(). Add run_services_once() for services with the run_once flag.
This commit is contained in:
195
bin/pt-agent
195
bin/pt-agent
@@ -4756,7 +4756,6 @@ use Percona::WebAPI::Resource::Agent;
|
||||
use Percona::WebAPI::Resource::Config;
|
||||
use Percona::WebAPI::Resource::Service;
|
||||
use Percona::WebAPI::Representation;
|
||||
use Percona::WebAPI::Util;
|
||||
|
||||
Percona::Toolkit->import(qw(_d Dumper have_required_args));
|
||||
Percona::WebAPI::Representation->import(qw(as_json as_config));
|
||||
@@ -5621,36 +5620,60 @@ sub get_services {
|
||||
curr_services => $curr_services,
|
||||
);
|
||||
|
||||
# First, save each service in --lib/services/. This must
|
||||
# be done before calling start_services() because that sub
|
||||
# looks for --lib/services/start-service, etc.
|
||||
# First, stop and remove services. Do this before write_services()
|
||||
# because this call looks for --lib/services/stop-service which
|
||||
# write_services() removes. I.e. use the service's stop- meta
|
||||
# counterpart (if any) before we remove the service.
|
||||
run_services(
|
||||
action => 'stop',
|
||||
services => $sorted_services->{removed},
|
||||
lib_dir => $lib_dir,
|
||||
bin_dir => $args{bin_dir}, # optional, for testing
|
||||
);
|
||||
|
||||
# Second, save each service in --lib/services/. Do this before
|
||||
# the next calls to run_services() because those calls look for
|
||||
# --lib/services/start-service which won't exist for new services
|
||||
# until written by this call.
|
||||
write_services(
|
||||
sorted_services => $sorted_services,
|
||||
lib_dir => $lib_dir,
|
||||
json => $args{json}, # optional, for testing
|
||||
);
|
||||
|
||||
# Start and restart services. This must be done before calling
|
||||
# schedule_services() so that, for example, start-query-history
|
||||
# is ran before query-history is scheduled and starts running.
|
||||
# Start new services and restart existing updated services.
|
||||
# Do this before calling schedule_services() so that, for example,
|
||||
# start-query-history is ran before query-history is scheduled
|
||||
# and starts running.
|
||||
|
||||
# Start new services.
|
||||
# TODO: this probably can't/won't fail, but if it does, is it
|
||||
# worth setting success=0?
|
||||
start_services(
|
||||
run_services(
|
||||
action => 'start',
|
||||
services => $sorted_services->{added},
|
||||
lib_dir => $lib_dir,
|
||||
bin_dir => $args{bin_dir}, # optional, for testing
|
||||
);
|
||||
|
||||
# Restart existing, re-configured services.
|
||||
start_services(
|
||||
restart => 1,
|
||||
# Restart existing updated services.
|
||||
run_services(
|
||||
action => 'restart',
|
||||
services => $sorted_services->{updated},
|
||||
lib_dir => $lib_dir,
|
||||
bin_dir => $args{bin_dir}, # optional, for testing
|
||||
);
|
||||
|
||||
# Run services with the run_once flag. Unlike run_services(),
|
||||
# this call runs the service directly, whether it's meta or not,
|
||||
# then it removes it from the services hashref so there's no
|
||||
# chance of running it again unless it's received again.
|
||||
run_services_once(
|
||||
services => $sorted_services->{services},
|
||||
lib_dir => $lib_dir,
|
||||
bin_dir => $args{bin_dir}, # optional, for testing
|
||||
);
|
||||
|
||||
# Schedule any services with a run_schedule or spool_schedule.
|
||||
# This must be called last, after write_services() and
|
||||
# start_services() because, for example, a service schedule
|
||||
@@ -5698,6 +5721,11 @@ sub sort_services {
|
||||
my $name = $service->name;
|
||||
$services->{$name} = $service;
|
||||
|
||||
# run_services() only needs real services, from which it can infer
|
||||
# certain meta-services like "start-foo" for real service "foo",
|
||||
# but write_services() needs meta-services too so it can know to
|
||||
# remove their files from --lib/services/.
|
||||
|
||||
if ( !exists $prev_services->{$name} ) {
|
||||
push @added, $service;
|
||||
}
|
||||
@@ -5866,7 +5894,87 @@ sub make_new_crontab {
|
||||
# from the real service's name. A service doesn't require meta-services;
|
||||
# there may be nothing to do to start it, in which case the real service
|
||||
# starts running due to its run_schedule and schedule_services().
|
||||
sub start_services {
|
||||
sub run_services {
|
||||
my (%args) = @_;
|
||||
have_required_args(\%args, qw(
|
||||
action
|
||||
services
|
||||
lib_dir
|
||||
)) or die;
|
||||
my $action = $args{action};
|
||||
my $services = $args{services};
|
||||
my $lib_dir = $args{lib_dir};
|
||||
|
||||
# Optional args
|
||||
my $bin_dir = defined $args{bin_dir} ? $args{bin_dir}
|
||||
: "$FindBin::Bin/";
|
||||
my $exec_cmd = $args{exec_cmd} || sub { return system(@_) };
|
||||
|
||||
my $env_vars = env_vars();
|
||||
my $log = "$lib_dir/logs/start-stop.log";
|
||||
my $cmd_fmt = ($env_vars ? "$env_vars " : '')
|
||||
. $bin_dir . "pt-agent --run-service %s >> $log 2>&1";
|
||||
|
||||
SERVICE:
|
||||
foreach my $service ( @$services ) {
|
||||
next if $service->meta; # only real services
|
||||
|
||||
my $name = $service->name;
|
||||
|
||||
# To restart, one must first stop, then start afterwards.
|
||||
if ( $action eq 'stop' || $action eq 'restart' ) {
|
||||
if ( -f "$lib_dir/services/stop-$name" ) {
|
||||
my $cmd = sprintf $cmd_fmt, "stop-$name";
|
||||
_info("Stopping $name: $cmd");
|
||||
$exec_cmd->($cmd);
|
||||
my $cmd_exit_status = $CHILD_ERROR >> 8;
|
||||
if ( $cmd_exit_status != 0 ) {
|
||||
_warn("Error stopping $name, check $log and "
|
||||
. "$lib_dir/logs/$name.run");
|
||||
next SERVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $action eq 'start' || $action eq 'restart' ) {
|
||||
# Remove old meta files. Meta files are generally temporary
|
||||
# in any case, persisting info from one interval to the next.
|
||||
# If the service has changed (e.g., report interval is longer),
|
||||
# there's no easy way to tranistion from old metadata to new,
|
||||
# so we just rm the old metadata and start anew.
|
||||
my $meta_files = "$lib_dir/meta/$name*";
|
||||
foreach my $meta_file ( glob $meta_files ) {
|
||||
if ( unlink $meta_file ) {
|
||||
_info("Removed $meta_file");
|
||||
}
|
||||
else {
|
||||
_warn("Cannot remove $meta_file: $OS_ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
# Start the service and wait for it to exit. If it dies
|
||||
# really early (before it really begins), our log file will
|
||||
# have the error; else, the service should automatically
|
||||
# switch to its default log file ending in ".run".
|
||||
if ( -f "$lib_dir/services/start-$name" ) {
|
||||
my $cmd = sprintf $cmd_fmt, "start-$name";
|
||||
_info("Starting $name: $cmd");
|
||||
$exec_cmd->($cmd);
|
||||
my $cmd_exit_status = $CHILD_ERROR >> 8;
|
||||
if ( $cmd_exit_status != 0 ) {
|
||||
_warn("Error starting $name, check $log and "
|
||||
."$lib_dir/logs/$name.run");
|
||||
next SERVICE;
|
||||
}
|
||||
_info("Started $name successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_services_once {
|
||||
my (%args) = @_;
|
||||
have_required_args(\%args, qw(
|
||||
services
|
||||
@@ -5882,62 +5990,27 @@ sub start_services {
|
||||
my $exec_cmd = $args{exec_cmd} || sub { return system(@_) };
|
||||
|
||||
my $env_vars = env_vars();
|
||||
my $log = "$lib_dir/logs/start.log";
|
||||
my $log = "$lib_dir/logs/run-once.log";
|
||||
my $cmd_fmt = ($env_vars ? "$env_vars " : '')
|
||||
. $bin_dir . "pt-agent --run-service %s >> $log 2>&1";
|
||||
|
||||
SERVICE:
|
||||
foreach my $service ( @$services ) {
|
||||
next if $service->meta; # only real services
|
||||
foreach my $name ( sort keys %$services ) {
|
||||
my $service = $services->{$name};
|
||||
next unless $service->run_once;
|
||||
|
||||
my $name = $service->name;
|
||||
delete $services->{$name};
|
||||
|
||||
# To restart, one must first stop, then start afterwards.
|
||||
if ( $restart ) {
|
||||
if ( -f "$lib_dir/services/stop-$name" ) {
|
||||
my $cmd = sprintf $cmd_fmt, "stop-$name";
|
||||
_info("Stopping $name: $cmd");
|
||||
$exec_cmd->($cmd);
|
||||
my $cmd_exit_status = $CHILD_ERROR >> 8;
|
||||
if ( $cmd_exit_status != 0 ) {
|
||||
_warn("Error stopping $name, check $log and "
|
||||
. "$lib_dir/logs/$name.run");
|
||||
next SERVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Remove old meta files. Meta files are generally temporary
|
||||
# in any case, persisting info from one interval to the next.
|
||||
# If the service has changed (e.g., report interval is longer),
|
||||
# there's no easy way to tranistion from old metadata to new,
|
||||
# so we just rm the old metadata and start anew.
|
||||
my $meta_files = "$lib_dir/meta/$name*";
|
||||
foreach my $meta_file ( glob $meta_files ) {
|
||||
if ( unlink $meta_file ) {
|
||||
_info("Removed $meta_file");
|
||||
}
|
||||
else {
|
||||
_warn("Cannot remove $meta_file: $OS_ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
# Start the service and wait for it to exit. If it dies
|
||||
# really early (before it really begins), our log file will
|
||||
# have the error; else, the service should automatically
|
||||
# switch to its default log file ending in ".run".
|
||||
if ( -f "$lib_dir/services/start-$name" ) {
|
||||
my $cmd = sprintf $cmd_fmt, "start-$name";
|
||||
_info("Starting $name: $cmd");
|
||||
$exec_cmd->($cmd);
|
||||
my $cmd_exit_status = $CHILD_ERROR >> 8;
|
||||
if ( $cmd_exit_status != 0 ) {
|
||||
_warn("Error starting $name, check $log and "
|
||||
."$lib_dir/logs/$name.run");
|
||||
next SERVICE;
|
||||
}
|
||||
_info("Started $name successfully");
|
||||
my $cmd = sprintf $cmd_fmt, "start-$name";
|
||||
_info("Running $name: $cmd");
|
||||
$exec_cmd->($cmd);
|
||||
my $cmd_exit_status = $CHILD_ERROR >> 8;
|
||||
if ( $cmd_exit_status != 0 ) {
|
||||
_warn("Error starting $name, check $log and "
|
||||
."$lib_dir/logs/$name.run");
|
||||
next SERVICE;
|
||||
}
|
||||
_info("Ran $name successfully");
|
||||
}
|
||||
|
||||
return;
|
||||
|
@@ -36,9 +36,10 @@ my $sample = "t/pt-agent/samples";
|
||||
# Create fake spool and lib dirs. Service-related subs in pt-agent
|
||||
# automatically add "/services" to the lib dir, but the spool dir is
|
||||
# used as-is.
|
||||
my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 1);
|
||||
mkdir "$tmpdir/spool" or die "Error making $tmpdir/spool: $OS_ERROR";
|
||||
mkdir "$tmpdir/services" or die "Error making $tmpdir/services: $OS_ERROR";
|
||||
my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 0);
|
||||
output(
|
||||
sub { pt_agent::init_lib_dir(lib_dir => $tmpdir) }
|
||||
);
|
||||
my $spool_dir = "$tmpdir/spool";
|
||||
|
||||
sub write_svc_files {
|
||||
@@ -88,9 +89,10 @@ my $output = output(
|
||||
sub {
|
||||
$exit_status = pt_agent::run_service(
|
||||
service => 'query-history',
|
||||
spool_dir => $spool_dir,
|
||||
lib_dir => $tmpdir,
|
||||
spool_dir => $spool_dir,
|
||||
Cxn => '',
|
||||
suffix => '', # optional, for testing
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -98,11 +100,11 @@ my $output = output(
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
"cat $tmpdir/spool/query-history",
|
||||
"cat $tmpdir/spool/query-history/query-history",
|
||||
"$sample/query-history/data001.json",
|
||||
),
|
||||
"1 run: spool data (query-history/data001.json)"
|
||||
);
|
||||
) or diag(`ls -l $tmpdir/spool/`);
|
||||
|
||||
chomp(my $n_files = `ls -1 $spool_dir | wc -l | awk '{print \$1}'`);
|
||||
is(
|
||||
@@ -116,7 +118,7 @@ is(
|
||||
0,
|
||||
"1 run: exit 0"
|
||||
);
|
||||
|
||||
exit;
|
||||
# #############################################################################
|
||||
# Service with two task, both using a program.
|
||||
# #############################################################################
|
||||
@@ -162,6 +164,7 @@ $output = output(
|
||||
spool_dir => $spool_dir,
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => '',
|
||||
suffix => '', # optional, for testing
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -291,6 +294,7 @@ SKIP: {
|
||||
spool_dir => $spool_dir,
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
suffix => '', # optional, for testing
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -318,6 +322,7 @@ SKIP: {
|
||||
spool_dir => $spool_dir,
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
suffix => '', # optional, for testing
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
@@ -341,6 +346,7 @@ SKIP: {
|
||||
spool_dir => $spool_dir,
|
||||
lib_dir => $tmpdir,
|
||||
Cxn => $cxn,
|
||||
suffix => '', # optional, for testing
|
||||
);
|
||||
},
|
||||
stderr => 1,
|
||||
|
Reference in New Issue
Block a user