/[sysadmin-cookbook]/recepies/zfs/zfs-replicate-pool.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /recepies/zfs/zfs-replicate-pool.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 268 - (show annotations)
Mon Sep 5 22:18:01 2011 UTC (12 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 2795 byte(s)
added sleep 0.1 s for netcat to start, verify snapshot creation
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 use Net::OpenSSH;
6 use Data::Dump qw(dump);
7 use List::Util qw(first);
8 use Time::Hires;
9
10 my $arh = Net::OpenSSH->new('root@10.60.0.204');
11 my $dev = Net::OpenSSH->new('root@10.60.0.202');
12
13 sub on {
14 my ($ssh,$command) = @_;
15 warn "## ", $ssh->get_host, "> $command\n";
16 if ( $command =~ m/zfs list/ ) {
17 map {
18 chomp; $_;
19 } $ssh->capture($command);
20 } else {
21 $ssh->capture($command);
22 }
23 }
24
25 print on $arh => 'zpool status';
26 print on $dev => 'zpool status';
27
28 my @arh = on $arh => 'zfs list -H -o name';
29 my @dev = on $dev => 'zfs list -H -o name';
30
31 warn "# ",dump( \@arh, \@dev );
32
33 my $from_pool = $arh[0];
34 my $to_pool = $dev[0];
35
36 sub snapshots_from {
37 my ($ssh) = @_;
38 my $host = $ssh->get_host;
39
40 my $snapshot;
41
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;
47 }
48
49 # warn "snapshots_from $host ",dump($snapshot),$/;
50
51 return $snapshot;
52 }
53
54 foreach my $fs ( @arh ) {
55
56 my $name = $fs;
57 $name =~ s{^$from_pool/}{} || next; # FIXME skip top-level fs
58 warn "? $name";
59
60 my $arh_snapshot = snapshots_from $arh;
61 if ( ! exists( $arh_snapshot->{$fs} ) ) {
62
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;
67 }
68
69 my $max_snapshot = $#{ $arh_snapshot->{$fs} };
70 warn "$max_snapshot snapshots of $fs on arh\n";
71
72 my $to_dev = "$to_pool/$name";
73
74 foreach my $i ( 0 .. $max_snapshot ) {
75 my $snap = $arh_snapshot->{$fs}->[$i] || die "no snap";
76
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";
81 next;
82 } else {
83 warn "- $name missing\n";
84 }
85 } else {
86 warn "$name not found on target yet";
87 }
88
89 my $snapshot;
90 if ( $i == 0 ) {
91 $snapshot = "$from_pool/$name\@$snap";
92 } else {
93 my $prev = $arh_snapshot->{$fs}->[$i-1] || die "no prev";
94 $snapshot = "-i $from_pool/$name\@$prev $from_pool/$name\@$snap";
95 }
96
97 warn "zfs transfer $snapshot -> $to_dev";
98
99 my $t = time();
100
101 my $recv = "nc -w 5 -l -p 8888 | zfs receive $to_dev";
102 warn ">> $recv\n";
103 my ($rin1,$pid1) = $dev->pipe_in($recv);
104 warn ">> pid: $pid1";
105
106 sleep 0.1; # FIXME wait for netcat to start
107
108 my $send = "zfs send $snapshot | nc -q 0 -w 5 10.60.0.202 8888";
109 warn "<< $send\n";
110 $arh->system($send);
111
112 $t = time() - $t;
113 warn "took $t seconds to complete\n";
114
115 $dev->system("zfs set readonly=on $to_pool/$name") if $i == 0;
116 die $dev->error if $dev->error;
117
118 $dev_snapshot = snapshots_from $dev;
119 die "can't find new snapshot $snap" unless $dev_snapshot->{$to_dev};
120
121 }
122
123 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26