| 1 |
#!/usr/bin/perl |
|---|
| 2 |
|
|---|
| 3 |
use strict; |
|---|
| 4 |
use Getopt::Long; |
|---|
| 5 |
use Data::Dumper; |
|---|
| 6 |
|
|---|
| 7 |
my %conf; |
|---|
| 8 |
my $CONF = q^/etc/zetaback_agent.conf^; |
|---|
| 9 |
use vars qw/$LIST $FULL $SNAP $ZFS $BASE $RESTORE/; |
|---|
| 10 |
|
|---|
| 11 |
GetOptions( |
|---|
| 12 |
"c=s" => \$CONF, |
|---|
| 13 |
"l" => \$LIST, |
|---|
| 14 |
"r" => \$RESTORE, |
|---|
| 15 |
"z=s" => \$ZFS, |
|---|
| 16 |
"d=s" => \$SNAP, |
|---|
| 17 |
"f=s" => \$FULL, |
|---|
| 18 |
"i=s" => \$BASE, |
|---|
| 19 |
); |
|---|
| 20 |
|
|---|
| 21 |
# Read out config in |
|---|
| 22 |
open(CONF, "<$CONF"); |
|---|
| 23 |
while(<CONF>) { /^\s*([^#](?:\S*)?)\s*=\s*(\S+)/ && ($conf{lc($1)} = $2); } |
|---|
| 24 |
close(CONF); |
|---|
| 25 |
|
|---|
| 26 |
sub zfs_agent_remove_snap { |
|---|
| 27 |
my $target = $ZFS . '@'; |
|---|
| 28 |
die "zfs_agent_remove_snap: insufficient args\n" unless($ZFS && $SNAP); |
|---|
| 29 |
if($SNAP eq '__zb_incr' or |
|---|
| 30 |
$SNAP =~ /__zb_full_\d+/) { |
|---|
| 31 |
$target .= $SNAP; |
|---|
| 32 |
} |
|---|
| 33 |
else { |
|---|
| 34 |
die "zfs_agent_remove_snap: illegal snap: $SNAP\n"; |
|---|
| 35 |
} |
|---|
| 36 |
`/usr/sbin/zfs destroy $target`; |
|---|
| 37 |
} |
|---|
| 38 |
|
|---|
| 39 |
sub zfs_agent_perform_full { |
|---|
| 40 |
my $target = $ZFS . '@__zb_full_' . $FULL; |
|---|
| 41 |
unless($ZFS && $FULL =~ /^\d+$/) { |
|---|
| 42 |
die "zfs_agent_perform_full: bad fs or snap name\n" |
|---|
| 43 |
} |
|---|
| 44 |
`/usr/sbin/zfs snapshot $target`; |
|---|
| 45 |
my @cmd = ("/usr/sbin/zfs", "send", $target); |
|---|
| 46 |
exec { $cmd[0] } @cmd; |
|---|
| 47 |
exit; |
|---|
| 48 |
} |
|---|
| 49 |
|
|---|
| 50 |
sub zfs_agent_perform_incremental { |
|---|
| 51 |
my $target = $ZFS . '@__zb_incr'; |
|---|
| 52 |
my $base = $ZFS . '@__zb_full_' . $BASE; |
|---|
| 53 |
unless($ZFS && $BASE) { |
|---|
| 54 |
die "zfs_agent_perform_incremental: bad args\n" |
|---|
| 55 |
} |
|---|
| 56 |
`/usr/sbin/zfs snapshot $target`; |
|---|
| 57 |
my @cmd = ("/usr/sbin/zfs", "send", "-i", $base, $target); |
|---|
| 58 |
exec { $cmd[0] } @cmd; |
|---|
| 59 |
exit; |
|---|
| 60 |
} |
|---|
| 61 |
|
|---|
| 62 |
sub zfs_agent_list { |
|---|
| 63 |
my %zfs; |
|---|
| 64 |
open(ZFSLIST, "/usr/sbin/zfs list -H |"); |
|---|
| 65 |
while(<ZFSLIST>) { |
|---|
| 66 |
chomp; |
|---|
| 67 |
my @line = split /\t/; |
|---|
| 68 |
if($line[0] =~ /$conf{pattern}/) { |
|---|
| 69 |
if($line[0] =~ /(\S+)\@([^\@]+)$/) { |
|---|
| 70 |
$zfs{$1} ||= []; |
|---|
| 71 |
push @{$zfs{$1}}, $2; |
|---|
| 72 |
} |
|---|
| 73 |
else { |
|---|
| 74 |
$zfs{$line[0]} ||= []; |
|---|
| 75 |
} |
|---|
| 76 |
} |
|---|
| 77 |
} |
|---|
| 78 |
close(ZFSLIST); |
|---|
| 79 |
|
|---|
| 80 |
foreach my $fs (sort keys %zfs) { |
|---|
| 81 |
print "$fs [".join(',',@{$zfs{$fs}})."]\n"; |
|---|
| 82 |
} |
|---|
| 83 |
} |
|---|
| 84 |
|
|---|
| 85 |
sub zfs_agent_perform_restore { |
|---|
| 86 |
my $fs = $ZFS; |
|---|
| 87 |
unless($ZFS && $RESTORE) { |
|---|
| 88 |
die "zfs_agent_perform_restore: bad state\n"; |
|---|
| 89 |
} |
|---|
| 90 |
my @cmd = ("/usr/sbin/zfs", "recv", $fs); |
|---|
| 91 |
exec { $cmd[0] } @cmd; |
|---|
| 92 |
exit; |
|---|
| 93 |
} |
|---|
| 94 |
|
|---|
| 95 |
if($LIST) { zfs_agent_list(); exit; } |
|---|
| 96 |
if($ZFS && $SNAP) { zfs_agent_remove_snap(); exit; } |
|---|
| 97 |
if($ZFS && $FULL) { zfs_agent_perform_full(); exit; } |
|---|
| 98 |
if($ZFS && $BASE) { zfs_agent_perform_incremental(); exit; } |
|---|
| 99 |
if($ZFS && $RESTORE) { zfs_agent_perform_restore(); exit; } |
|---|