blob: c3ff4fbca16222aca37b4bf44f4f5bc34e68d103 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
#!/usr/bin/perl
use DBI;
use Data::Dumper;
use warnings;
use strict;
my $mountpoint = "/var/backups/bytemyback/mnt/";
my $snapshot_name = "byteback_data_snap";
my $snapshot_size = "20G";
my $dbh;
die "Must specify either pre or post\n" unless @ARGV;
if ($ARGV[0] eq 'pre') {
# Check snapshot doesn't already exist
die "Snapshot still exists\n" if `lvs 2>&1` =~ /$snapshot_name/;
my $lock_tables = 1; # This will be configurable. Whether or not it runs FLUSH TABLES WITH READ LOCK before taking the snapshot.
my $defaults_file = '/etc/mysql/debian.cnf';
my $dsn = "DBI:mysql:;mysql_read_default_file=$defaults_file";
$dbh = DBI->connect(
$dsn,
undef,
undef,
{RaiseError => 1}
) or die "DBI::errstr: $DBI::errstr";
my $data_dir = ask_mysql_for_var('datadir');
my $lvm_dir = get_LVM_dir();
die "MySQL doesn't seem to be running from LVM\n" if !$lvm_dir;
$dbh->do("FLUSH TABLES WITH READ LOCK") if $lock_tables;
# Create snapshot
my $mounted_lvm = `df $lvm_dir | tail -n1 | cut -f1 -d" "`;
if (!`lvcreate -n $snapshot_name -L $snapshot_size --snapshot $mounted_lvm`) {
my $error = $!;
$dbh->do("UNLOCK TABLES") if $lock_tables;
die("Unable to create snapshot: $!\n");
}
else {
$dbh->do("UNLOCK TABLES") if $lock_tables;
chomp (my $mapped_snapshot = "/dev/mapper/" . `dmsetup ls | grep $snapshot_name | grep -v cow | cut -f1 -d " "`);
`mkdir -p $mountpoint`;
`mount $mapped_snapshot $mountpoint`;
`touch ${mountpoint}.bytebacklvm`;
}
}
elsif ($ARGV[0] eq 'post') {
`umount $mountpoint`;
chomp (my $mapped_snapshot = "/dev/mapper/" . `dmsetup ls | grep $snapshot_name | grep -v cow | cut -f1 -d " "`);
`lvremove -f $mapped_snapshot`;
}
sub ask_mysql_for_var {
my $var = '@@' . shift;
my $query = $dbh->prepare("SELECT ${var}");
$query->execute;
return $query->fetchrow_hashref()->{$var};
}
sub get_LVM_dir {
# This is a bit hacky, it checks if lvs returns,
# then checks if the mountpoint is /dev/mapper/$firstbit-$secondbit
# Returns true only if above matches and lvs output has $secondbit $firstbit somewhere
my $datadir = ask_mysql_for_var('datadir');
my $lvs = `lvs 2>&1`;
if (($?) || ($lvs =~ /No volume groups found/)) {
return 0;
}
my $output = `df $datadir | tail -n1`;
$output =~ s/--/:/g;
if ($output =~ m#/dev/mapper/([\w:]+)-([\w:]+)\s#) {
my ($vg, $lv) = ($1, $2);
$vg =~ s/:/-/; $lv =~ s/:/-/;
if ($lvs =~ /\s+$lv\s+$vg\s/) {
return $datadir;
}
}
return 0;
}
|