6 use Data::Dump qw(dump);
7 use List::Util qw(first);
10 my $arh = Net::OpenSSH->new('root@10.60.0.204');
11 my $dev = Net::OpenSSH->new('root@10.60.0.202');
14 my ($ssh,$command) = @_;
15 warn "## ", $ssh->get_host, "> $command\n";
16 if ( $command =~ m/zfs list/ ) {
19 } $ssh->capture($command);
21 $ssh->capture($command);
25 print on $arh => 'zpool status';
26 print on $dev => 'zpool status';
28 my @arh = on $arh => 'zfs list -H -o name';
29 my @dev = on $dev => 'zfs list -H -o name';
31 warn "# ",dump( \@arh, \@dev );
33 my $from_pool = $arh[0];
34 my $to_pool = $dev[0];
38 my $host = $ssh->get_host;
42 my @snapshots = on $ssh => 'zfs list -H -t snapshot -o name';
43 die $ssh->error if $ssh->error;
44 foreach my $s (@snapshots) {
45 my ($fs,$name) = split(/\@/,$s);
46 push @{ $snapshot->{$fs} }, $name;
49 # warn "snapshots_from $host ",dump($snapshot),$/;
54 foreach my $fs ( @arh ) {
57 $name =~ s{^$from_pool/}{} || next; # FIXME skip top-level fs
60 my $arh_snapshot = snapshots_from $arh;
61 if ( ! exists( $arh_snapshot->{$fs} ) ) {
63 my $snapshot = $fs . '@send';
64 print on $arh => "zfs snapshot $snapshot";
65 die $arh->error if $arh->error;
66 $arh_snapshot = snapshots_from $arh;
69 my $max_snapshot = $#{ $arh_snapshot->{$fs} };
70 warn "$max_snapshot snapshots of $fs on arh\n";
72 my $to_dev = "$to_pool/$name";
74 foreach my $i ( 0 .. $max_snapshot ) {
75 my $snap = $arh_snapshot->{$fs}->[$i] || die "no snap";
77 my $dev_snapshot = snapshots_from $dev;
78 if ( exists $dev_snapshot->{$to_dev} ) {
79 if ( first { /^\Q$snap\E$/ } @{ $dev_snapshot->{$to_dev} } ) {
80 warn "+ $name exists\n";
83 warn "- $name missing\n";
86 warn "$name not found on target yet";
91 $snapshot = "$from_pool/$name\@$snap";
93 my $prev = $arh_snapshot->{$fs}->[$i-1] || die "no prev";
94 $snapshot = "-i $from_pool/$name\@$prev $from_pool/$name\@$snap";
97 warn "zfs transfer $snapshot -> $to_dev";
101 my $recv = "nc -w 5 -l -p 8888 | zfs receive $to_dev";
103 my ($rin1,$pid1) = $dev->pipe_in($recv);
104 warn ">> pid: $pid1";
106 sleep 0.1; # FIXME wait for netcat to start
108 my $send = "zfs send $snapshot | nc -q 0 -w 5 10.60.0.202 8888";
113 warn "took $t seconds to complete\n";
115 $dev->system("zfs set readonly=on $to_pool/$name") if $i == 0;
116 die $dev->error if $dev->error;
118 $dev_snapshot = snapshots_from $dev;
119 die "can't find new snapshot $snap" unless $dev_snapshot->{$to_dev};