| 28 |
rodolico |
1 |
#! /usr/bin/env perl
|
|
|
2 |
|
|
|
3 |
use strict;
|
|
|
4 |
use warnings;
|
|
|
5 |
use Data::Dumper;
|
|
|
6 |
|
|
|
7 |
# create an encrypted ZFS pool using geli
|
|
|
8 |
# @DATADRIVES: list of drives to use for data
|
|
|
9 |
# @DEDUPDRIVES: list of drives to use for deduplication (optional)
|
|
|
10 |
# $RAIDLEVEL: raidz, raidz2, mirror, etc.
|
|
|
11 |
# $pool: name of the pool to create
|
|
|
12 |
# $poolSettings: settings to apply to the pool after creation
|
|
|
13 |
# $combinedKeyFile: path to the combined geli key file, passed as first argument
|
|
|
14 |
|
|
|
15 |
my @DATADRIVES=qw'da7 da6'; # list of all drives to use
|
|
|
16 |
my @DEDUPDRIVES= (); # list of drives to use for deduplication (optional)
|
|
|
17 |
my $RAIDLEVEL = 'mirror'; # Raid level to create: mirror raidz raidz2
|
|
|
18 |
my $pool = 'backup'; # pool name to create. Destoyed if it exists
|
|
|
19 |
my $poolSettings = "atime=off compress=gzip-9 volmode=full"; # settings to apply to the pool after creation
|
|
|
20 |
$poolSettings .= ' dedup=on' if @DEDUPDRIVES; # if dedup drives are used, enable dedup on pool
|
|
|
21 |
|
|
|
22 |
my @alldrives = (@DATADRIVES,@DEDUPDRIVES);
|
|
|
23 |
my $alldrives = join( ' ', @alldrives );
|
|
|
24 |
|
|
|
25 |
|
|
|
26 |
sub runCommand {
|
|
|
27 |
my $command = shift;
|
|
|
28 |
print "$command\n";
|
| 29 |
rodolico |
29 |
#`$command`;
|
| 28 |
rodolico |
30 |
}
|
|
|
31 |
|
| 29 |
rodolico |
32 |
my $combinedKeyFile = shift;
|
|
|
33 |
die "No combined key file provided\n" unless defined $combinedKeyFile;
|
|
|
34 |
|
| 28 |
rodolico |
35 |
# destroy the pool, if it exists
|
|
|
36 |
if ( `zpool list -H | grep '^$pool'` ) {
|
|
|
37 |
&runCommand( "zpool destroy $pool" );
|
|
|
38 |
}
|
|
|
39 |
|
|
|
40 |
|
|
|
41 |
# if geli sees some disks already created, detach and clear them.
|
|
|
42 |
my @disks = `geli status | grep '^da' | cut -d' ' -f1 2>/dev/null`;
|
|
|
43 |
chomp @disks;
|
|
|
44 |
if ( join ' ', @disks ) {
|
|
|
45 |
warn "Detaching and clearing existing geli disks: " . join( ' ', @disks ) . "\nPress Enter to continue...";
|
|
|
46 |
<>;
|
|
|
47 |
my $temp = join( ' ', @disks );
|
|
|
48 |
&runCommand( "geli detach $temp" ); # detach first
|
|
|
49 |
$temp =~ s/\.eli//g; # remove .eli extension
|
|
|
50 |
&runCommand( "geli clear $temp"); # clear after detaching
|
|
|
51 |
}
|
|
|
52 |
|
|
|
53 |
# remove any partitions from the drives
|
|
|
54 |
my @partitionedDrives = `gpart list -a | grep 'Geom name:' | rev | cut -d' ' -f1 | rev`;
|
|
|
55 |
chomp @partitionedDrives;
|
|
|
56 |
my %partitionedDrives = map{ $_=>1 } @partitionedDrives;
|
|
|
57 |
|
|
|
58 |
# remove any partitions from the drives we are going to use
|
|
|
59 |
foreach my $drive ( @DATADRIVES,@DEDUPDRIVES ) {
|
|
|
60 |
&runCommand( "gpart destroy -F $drive" ) if $partitionedDrives{$drive};
|
|
|
61 |
}
|
|
|
62 |
|
| 29 |
rodolico |
63 |
&runCommand( "geli init -e AES-XTS -l 256 -s 4096 -K $combinedKeyFile -P " . join( ' ', @alldrives ) );
|
| 28 |
rodolico |
64 |
&runCommand( "geli configure -t " . join( ' ', @alldrives ) );
|
|
|
65 |
&runCommand( "geli attach -k $combinedKeyFile -p " . join( ' ', @alldrives ) );
|
|
|
66 |
|
|
|
67 |
&runCommand(
|
|
|
68 |
"zpool create -f $pool $RAIDLEVEL " .
|
|
|
69 |
join( ' ', map{ $_ . '.eli' } @DATADRIVES) .
|
|
|
70 |
( @DEDUPDRIVES ? ' dedup mirror ' . join( ' ', map{ $_ . '.eli' } @DEDUPDRIVES) : '' ) );
|
|
|
71 |
&runCommand( "zfs set $poolSettings $pool" );
|
|
|
72 |
|
|
|
73 |
|
|
|
74 |
1;
|