/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 267 - (hide annotations)
Mon Sep 5 22:02:00 2011 UTC (12 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 2619 byte(s)
replicate all filesystems and snapshots to another machine

1 dpavlin 267 #!/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    
9     my $arh = Net::OpenSSH->new('root@10.60.0.204');
10     my $dev = Net::OpenSSH->new('root@10.60.0.202');
11    
12     sub on {
13     my ($ssh,$command) = @_;
14     warn "## ", $ssh->get_host, "> $command\n";
15     if ( $command =~ m/zfs list/ ) {
16     map {
17     chomp; $_;
18     } $ssh->capture($command);
19     } else {
20     $ssh->capture($command);
21     }
22     }
23    
24     print on $arh => 'zpool status';
25     print on $dev => 'zpool status';
26    
27     my @arh = on $arh => 'zfs list -H -o name';
28     my @dev = on $dev => 'zfs list -H -o name';
29    
30     warn "# ",dump( \@arh, \@dev );
31    
32     my $from_pool = $arh[0];
33     my $to_pool = $dev[0];
34    
35     sub snapshots_from {
36     my ($ssh) = @_;
37     my $host = $ssh->get_host;
38    
39     my $snapshot;
40    
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;
46     }
47    
48     warn "snapshots_from $host ",dump($snapshot),$/;
49    
50     return $snapshot;
51     }
52    
53     foreach my $fs ( @arh ) {
54    
55     my $name = $fs;
56     $name =~ s{^$from_pool/}{} || next; # FIXME skip top-level fs
57     warn "? $name";
58    
59     my $arh_snapshot = snapshots_from $arh;
60     if ( ! exists( $arh_snapshot->{$fs} ) ) {
61    
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;
66     }
67    
68     my $max_snapshot = $#{ $arh_snapshot->{$fs} };
69     warn "$max_snapshot snapshots of $fs on arh\n";
70    
71     my $to_dev = "$to_pool/$name";
72    
73     foreach my $i ( 0 .. $max_snapshot ) {
74     my $snap = $arh_snapshot->{$fs}->[$i] || die "no snap";
75    
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";
80     next;
81     } else {
82     warn "- $name missing\n";
83     }
84     } else {
85     warn "$name not found on target yet";
86     }
87    
88     my $snapshot;
89     if ( $i == 0 ) {
90     $snapshot = "$from_pool/$name\@$snap";
91     } else {
92     my $prev = $arh_snapshot->{$fs}->[$i-1] || die "no prev";
93     $snapshot = "-i $from_pool/$name\@$prev $from_pool/$name\@$snap";
94     }
95    
96     warn "zfs transfer $snapshot -> $to_dev";
97    
98     my $t = time();
99    
100     my $recv = "nc -w 5 -l -p 8888 | zfs receive $to_dev";
101     warn ">> $recv\n";
102     my ($rin1,$pid1) = $dev->pipe_in($recv);
103     warn ">> pid: $pid1";
104    
105     my $send = "zfs send $snapshot | nc -q 0 -w 5 10.60.0.202 8888";
106     warn "<< $send\n";
107     $arh->system($send);
108    
109     $t = time() - $t;
110     warn "took $t seconds to complete\n";
111    
112     $dev->system("zfs set readonly=on $to_pool/$name") if $i == 0;
113     die $dev->error if $dev->error;
114    
115     }
116    
117     }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26