6 use Data::Dump qw(dump);
7 use List::Util qw(first);
10 my $compress = '| lzop -c';
11 my $decompress = 'lzop -d |';
13 my $arh = Net::OpenSSH->new('root@10.60.0.204');
14 my $dev = Net::OpenSSH->new('root@10.60.0.202');
17 my ($ssh,$command) = @_;
18 warn "## ", $ssh->get_host, "> $command\n" if $ENV{DEBUG};
19 if ( $command =~ m/zfs list/ ) {
22 } $ssh->capture($command);
24 $ssh->capture($command);
28 print on $arh => 'zpool status';
29 print on $dev => 'zpool status';
31 my @arh = on $arh => 'zfs list -H -o name';
32 my @dev = on $dev => 'zfs list -H -o name';
34 warn "# ",dump( \@arh, \@dev );
36 my $from_pool = $arh[0];
37 my $to_pool = $dev[0];
41 my $host = $ssh->get_host;
45 my @snapshots = on $ssh => 'zfs list -H -t snapshot -o name';
46 die $ssh->error if $ssh->error;
47 foreach my $s (@snapshots) {
48 my ($fs,$name) = split(/\@/,$s);
49 push @{ $snapshot->{$fs} }, $name;
52 # warn "snapshots_from $host ",dump($snapshot),$/;
57 foreach my $fs ( @arh ) {
60 $name =~ s{^$from_pool/}{} || next; # FIXME skip top-level fs
63 my $arh_snapshot = snapshots_from $arh;
64 if ( ! exists( $arh_snapshot->{$fs} ) ) {
66 my $snapshot = $fs . '@send';
67 print on $arh => "zfs snapshot $snapshot";
68 die $arh->error if $arh->error;
69 $arh_snapshot = snapshots_from $arh;
72 my $max_snapshot = $#{ $arh_snapshot->{$fs} };
73 warn "$fs has ",$max_snapshot+1," snapshots\n";
75 my $to_dev = "$to_pool/$name";
77 foreach my $i ( 0 .. $max_snapshot ) {
78 my $snap = $arh_snapshot->{$fs}->[$i] || die "no snap";
80 my $dev_snapshot = snapshots_from $dev;
81 if ( exists $dev_snapshot->{$to_dev} ) {
82 if ( first { /^\Q$snap\E$/ } @{ $dev_snapshot->{$to_dev} } ) {
83 warn "+ $name @ $snap exists\n";
86 warn "- $name @ $snap missing\n";
89 warn "$name not found on target yet";
94 $snapshot = "$from_pool/$name\@$snap";
96 my $prev = $arh_snapshot->{$fs}->[$i-1] || die "no prev";
97 $snapshot = "-i $from_pool/$name\@$prev $from_pool/$name\@$snap";
100 warn "zfs transfer $snapshot -> $to_dev\n";
104 my $recv = "nc -w 3 -l -p 8888 | $decompress zfs receive $to_dev";
106 my ($rin1,$pid1) = $dev->pipe_in($recv);
107 warn ">> pid: $pid1";
109 sleep 1; # FIXME wait for netcat to start
111 my $send = "zfs send $snapshot $compress | nc -q 0 -w 2 10.60.0.202 8888";
114 die $arh->error if $arh->error;
117 warn "took $t seconds to complete\n";
119 $dev->system("zfs set readonly=on $to_pool/$name") if $i == 0;
120 warn "ERROR: ",$dev->error if $dev->error;
123 $dev_snapshot = snapshots_from $dev;
124 die "can't find new snapshot $snap" unless $dev_snapshot->{$to_dev};