aboutsummaryrefslogtreecommitdiffstats
path: root/send-backup.pl
blob: ac12f32e4e5029cf4be5cc13e1fcdaad68cc9d61 (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
#!/usr/bin/env perl

use strict;
use warnings;

use YAML::Tiny;
use Data::Dumper;

my $conffile = 'backup.conf';

my $conf = YAML::Tiny->read($conffile);
my $srcs = $conf->[0]->{sources};
my $dest = $conf->[0]->{dest};

system("zfs list $dest > /dev/null 2>&1") == 0 or
  die "Error: pool '$dest' not found. Is it imported?\n";

foreach my $src (@$srcs) {
  my ($pool, $fs) = split(/\//, $src, 2);
  my ($from, $to) = limits($pool, $dest, $fs);

  unless (defined $from) {
    print "Warning: $dest does not contain $fs. Initialize with:\n" .
      "\tzfs send -R $pool/$to | zfs recv $dest/$fs\n";
    next;
  }

  if ($from eq $to) {
    print "No new snapshots for $pool/$fs.\n";
    next;
  }

  print "Sending to $dest: $pool/$from -> $to\n";
  my $cmd = "zfs send -RI $pool/$from $pool/$to | zfs recv $dest/$fs";
  system($cmd) == 0 or die "Error: couldn't send snapshots with:\n\t$cmd\n."
}

sub limits {
  my ($src, $dst, $fs) = @_;

  my @dstsnaps = snaps("$dst/$fs");
  my @srcsnaps = snaps("$src/$fs");

  ($dstsnaps[$#dstsnaps], $srcsnaps[$#srcsnaps]);
}

sub snaps {
  my $fs = shift;

  map {
    chomp;
    (split /\//, $_, 2)[1];
  } `zfs list -Ht snap -d 1 -o name -s creation $fs`;
}