Create lib/Safeguards.pm to implement new --disk-bytes-free and --disk-pct-free in pt-agent.

This commit is contained in:
Daniel Nichter
2013-05-15 13:27:44 -07:00
parent 635ad149ba
commit 84c8906de4
3 changed files with 190 additions and 6 deletions

View File

@@ -7746,7 +7746,7 @@ Once the previous step are complete, run:
$ pt-agent --daemonize $ pt-agent --daemonize
The tool daemonizes and continues running in the background. The agent daemonizes and continues running in the background.
=item 5. Configure the agent at L<https://pws.percona.com> =item 5. Configure the agent at L<https://pws.percona.com>
@@ -7812,7 +7812,7 @@ See the L<"--help"> output for a list of default config files.
=item --daemonize =item --daemonize
Daemonize the tool. This causes the tool to fork into the background and Daemonize the agent. This causes the agent to fork into the background and
L<"--log"> all output. L<"--log"> all output.
Fork to the background and detach from the shell. POSIX operating systems only. Fork to the background and detach from the shell. POSIX operating systems only.
@@ -7824,9 +7824,30 @@ short form: -F; type: string
Only read MySQL options from the given file. You must give an absolute Only read MySQL options from the given file. You must give an absolute
pathname. pathname.
=item --disk-bytes-free
type: size; default: 100M
Stop all services if the disk has less than this much free space.
This prevents the agent from filling up the disk with service data.
Valid size value suffixes are k, M, G, and T.
=item --disk-pct-free
type: int; default: 5
Stop all services if the disk has less than this percent free space.
This prevents the agent from filling up the disk with service data.
This option works similarly to L<"--disk-bytes-free"> but specifies a
percentage margin of safety instead of a bytes margin of safety.
The agent honors both options, and will not collect any data unless both
margins are satisfied.
=item --help =item --help
Print the tool's help and exit. Print the agent's help and exit.
=item --host =item --host
@@ -7911,7 +7932,7 @@ type: Array
Set the MySQL variables in this comma-separated list of C<variable=value> pairs. Set the MySQL variables in this comma-separated list of C<variable=value> pairs.
By default, the tool sets: By default, the agent sets:
=for comment ignore-pt-internal-value =for comment ignore-pt-internal-value
MAGIC_set_vars MAGIC_set_vars
@@ -7922,7 +7943,7 @@ Variables specified on the command line override these defaults. For
example, specifying C<--set-vars wait_timeout=500> overrides the default example, specifying C<--set-vars wait_timeout=500> overrides the default
value of C<10000>. value of C<10000>.
The tool prints a warning and continues if a variable cannot be set. The agent prints a warning and continues if a variable cannot be set.
=item --socket =item --socket
@@ -7956,7 +7977,7 @@ MySQL user, if not the current system user.
=item --version =item --version
Print the tool's version and exit. Print the agent's version and exit.
=back =back

94
lib/Safeguards.pm Normal file
View File

@@ -0,0 +1,94 @@
# This program is copyright 2013 Percona Ireland Ltd.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
# licenses.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# ###########################################################################
# Safeguards package
# ###########################################################################
package Safeguards;
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
sub new {
my ($class, %args) = @_;
my $self = {
disk_bytes_free => $args{disk_bytes_free} || 104857600, # 100 MiB
disk_pct_free => $args{disk_pct_free} || 5,
};
return bless $self, $class;
}
sub get_disk_space {
my ($self, %args) = @_;
my $filesystem = $args{filesystem} || $ENV{PWD};
# Filesystem 1024-blocks Used Available Capacity Mounted on
# /dev/disk0s2 118153176 94409664 23487512 81% /
my $disk_space = `df -P -k "$filesystem"`;
chop($disk_space) if $disk_space;
PTDEBUG && _d('Disk space on', $filesystem, $disk_space);
return $disk_space;
}
sub check_disk_space() {
my ($self, %args) = @_;
my $disk_space = $args{disk_space};
PTDEBUG && _d("Checking disk space:\n", $disk_space);
# There may be other info, so extract just the partition line,
# i.e. the first line starting with /, as in:
# Filesystem 1024-blocks Used Available Capacity Mounted on
# /dev/disk0s2 118153176 94409664 23487512 81% /
my ($partition) = $disk_space =~ m/^\s*(\/.+)/m;
PTDEBUG && _d('Partition:', $partition);
die "Failed to parse partition from disk space:\n$disk_space"
unless $partition;
# Parse the partition line.
my (undef, undef, $bytes_used, $bytes_free, $pct_used, undef)
= $partition =~ m/(\S+)/g;
PTDEBUG && _d('Bytes used:', $bytes_used, 'free:', $bytes_free,
'Percentage used:', $pct_used);
# Convert 1024-blocks blocks to bytes.
$bytes_used = ($bytes_used || 0) * 1024;
$bytes_free = ($bytes_free || 0) * 1024;
# Convert pct used to free.
$pct_used =~ s/%//;
my $pct_free = 100 - ($pct_used || 0);
# Return true if both thresholds are ok.
return $bytes_free >= $self->{disk_bytes_free}
&& $pct_free >= $self->{disk_pct_free};
}
sub _d {
my ($package, undef, $line) = caller 0;
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
map { defined $_ ? $_ : 'undef' }
@_;
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
}
1;
# ###########################################################################
# End Safeguards package
# ###########################################################################

69
t/lib/Safeguards.t Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use Safeguards;
use Percona::Test;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Quotekeys = 0;
my $sample = "t/lib/samples/bash/";
my $safeguards = Safeguards->new(
disk_bytes_free => 104857600,
disk_pct_free => 10,
);
# Filesystem 1024-blocks Used Available Capacity Mounted on
# /dev/disk0s2 118153176 94409664 23487512 81% /
#
# Those values are in Kb, so:
# used = 94409664 (94.4G) = 96_675_495_936 bytes
# free = 23487512 (23.4G) = 24_051_212_288 bytes
# pct free = 100 - 81 = 19 %
my $df = slurp_file("$trunk/$sample/diskspace001.txt");
ok(
$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Enough bytes and pct free"
);
$safeguards = Safeguards->new(
disk_bytes_free => 104857600,
disk_pct_free => 20,
);
ok(
!$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Not enough pct free"
);
$safeguards = Safeguards->new(
disk_bytes_free => 24_051_212_289,
disk_pct_free => 5,
);
ok(
!$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Not enough bytes free"
);
done_testing;