6 use Data::Dump qw(dump);
7 use List::Util qw(first);
9 my $arh = Net::OpenSSH->new('root@10.60.0.204');
10 my $dev = Net::OpenSSH->new('root@10.60.0.202');
13 my ($ssh,$command) = @_;
14 warn "## ", $ssh->get_host, "> $command\n";
15 if ( $command =~ m/zfs list/ ) {
18 } $ssh->capture($command);
20 $ssh->capture($command);
24 print on $arh => 'zpool status';
25 print on $dev => 'zpool status';
27 my @arh = on $arh => 'zfs list -H -o name';
28 my @dev = on $dev => 'zfs list -H -o name';
30 warn "# ",dump( \@arh, \@dev );
32 my $from_pool = $arh[0];
33 my $to_pool = $dev[0];
37 my $host = $ssh->get_host;
41 my @snapshots = on $ssh => 'zfs list -H -t snapshot -o name';
42 die $ssh->error if $ssh->error;
43 foreach my $s (@snapshots) {
44 my ($fs,$name) = split(/\@/,$s);
45 push @{ $snapshot->{$fs} }, $name;
48 warn "snapshots_from $host ",dump($snapshot),$/;
53 foreach my $fs ( @arh ) {
56 $name =~ s{^$from_pool/}{} || next; # FIXME skip top-level fs
59 my $arh_snapshot = snapshots_from $arh;
60 if ( ! exists( $arh_snapshot->{$fs} ) ) {
62 my $snapshot = $fs . '@send';
63 print on $arh => "zfs snapshot $snapshot";
64 die $arh->error if $arh->error;
65 $arh_snapshot = snapshots_from $arh;
68 my $max_snapshot = $#{ $arh_snapshot->{$fs} };
69 warn "$max_snapshot snapshots of $fs on arh\n";
71 my $to_dev = "$to_pool/$name";
73 foreach my $i ( 0 .. $max_snapshot ) {
74 my $snap = $arh_snapshot->{$fs}->[$i] || die "no snap";
76 my $dev_snapshot = snapshots_from $dev;
77 if ( exists $dev_snapshot->{$to_dev} ) {
78 if ( first { /^\Q$snap\E$/ } @{ $dev_snapshot->{$to_dev} } ) {
79 warn "+ $name exists\n";
82 warn "- $name missing\n";
85 warn "$name not found on target yet";
90 $snapshot = "$from_pool/$name\@$snap";
92 my $prev = $arh_snapshot->{$fs}->[$i-1] || die "no prev";
93 $snapshot = "-i $from_pool/$name\@$prev $from_pool/$name\@$snap";
96 warn "zfs transfer $snapshot -> $to_dev";
100 my $recv = "nc -w 5 -l -p 8888 | zfs receive $to_dev";
102 my ($rin1,$pid1) = $dev->pipe_in($recv);
103 warn ">> pid: $pid1";
105 my $send = "zfs send $snapshot | nc -q 0 -w 5 10.60.0.202 8888";
110 warn "took $t seconds to complete\n";
112 $dev->system("zfs set readonly=on $to_pool/$name") if $i == 0;
113 die $dev->error if $dev->error;