Subversion Repositories zfs_utils

Rev

Rev 27 | Rev 31 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 27 Rev 30
Line 194... Line 194...
194
 
194
 
195
 
195
 
196
 
196
 
197
sub mountGeli {
197
sub mountGeli {
198
   my $geliConfig = shift;
198
   my $geliConfig = shift;
199
   unless ( -e $geliConfig->{'localKey'} ) {
199
   unless ( $geliConfig->{'localKey'} ) {
200
      logMsg "Could not find local key file: " . $geliConfig->{'localKey'} . "\n";
200
      logMsg "Could not find local key in configuration file\n";
201
      return '';
201
      return '';
202
   }
202
   }
203
   # find the keyfile disk and mount it
203
   # find the keyfile disk and mount it
204
   my $path = mountDriveByLabel( $geliConfig->{'keydiskname'} );
204
   my $path = mountDriveByLabel( $geliConfig->{'keydiskname'} );
205
   unless ( $path ne '' and -e "$path/" . $geliConfig->{'keyfile'} ) {
205
   unless ( $path ne '' and -e "$path/" . $geliConfig->{'keyfile'} ) {
Line 215... Line 215...
215
   my $poolname = decryptAndMountGeli( $geliConfig );
215
   my $poolname = decryptAndMountGeli( $geliConfig );
216
   return $poolname;
216
   return $poolname;
217
                                                
217
                                                
218
}
218
}
219
 
219
 
-
 
220
# find all disks which are candidates for use with geli/zfs
-
 
221
# Grabs all disks on the system, then removes those with partitions
-
 
222
# and those already used in zpools.
-
 
223
sub findGeliDisks {
-
 
224
   logMsg("Finding available disks for GELI/ZFS use");
-
 
225
   # get all disks in system
-
 
226
   my %allDisks = map{ chomp $_ ; $_ => 1 } runCmd( "geom disk list | grep 'Geom name:' | rev | cut -d' ' -f1 | rev" );
-
 
227
   # get the disks with partitions
-
 
228
   my @temp = runCmd( "gpart show -p | grep '^=>'");  # -p prints just the disks without partitions
-
 
229
   # remove them from the list
-
 
230
   foreach my $disk ( @temp ) {
-
 
231
      $allDisks{$1} = 0 if ( $disk =~ m/^=>[\t\s0-9]+([a-z][a-z0-9]+)/ ) ;
-
 
232
   }
-
 
233
 
-
 
234
   # get disk which are currently used for zpools
-
 
235
   @temp = runCmd( "zpool status -LP | grep '/dev/'" );
-
 
236
   foreach my $disk ( @temp ) {
-
 
237
      $allDisks{$1} = 0 if  $disk =~ m|/dev/([a-z]+\d+)|;
-
 
238
   }
-
 
239
 
-
 
240
   # return only the disks which are free (value 1)
-
 
241
   return grep{ $allDisks{$_} == 1 } keys %allDisks;
-
 
242
}
-
 
243
 
220
## Decrypt each GELI disk from $geliConfig->{'diskList'} using the keyfile,
244
## Decrypt each GELI disk from $geliConfig->{'diskList'} using the keyfile,
221
## then import and mount the ZFS pool specified in $geliConfig->{'poolname'}.
245
## then import and mount the ZFS pool specified in $geliConfig->{'poolname'}.
222
##
246
##
223
## Returns the pool name on success, empty on error.
247
## Returns the pool name on success, empty on error.
224
sub decryptAndMountGeli {
248
sub decryptAndMountGeli {
225
   my ($geliConfig) = @_;
249
   my ($geliConfig) = @_;
-
 
250
   
226
   # these are configuration sanity checks, so die if they fail
251
   # Can't continue at all if no pool name
227
   die "No disk list found in GELI config\n" unless $geliConfig->{'diskList'};
-
 
228
   die "No pool name specified in config\n" unless $geliConfig->{'poolname'};
252
   die "No pool name specified in config\n" unless $geliConfig->{'poolname'};
-
 
253
   # if no list of disks provided, try to find them
-
 
254
   $geliConfig->{'diskList'} //= findGeliDisks();
229
 
255
   
230
   my $diskList = $geliConfig->{'diskList'};
256
   my $diskList = $geliConfig->{'diskList'};
231
   my $poolname = $geliConfig->{'poolname'};
257
   my $poolname = $geliConfig->{'poolname'};
232
   my $keyfile = $geliConfig->{'target'};
258
   my $keyfile = $geliConfig->{'target'};
233
   unless ( -e $keyfile ) {
259
   unless ( -e $keyfile ) {
234
      logMsg "GELI keyfile $keyfile does not exist\n";
260
      logMsg "GELI keyfile $keyfile does not exist\n";
Line 236... Line 262...
236
   }
262
   }
237
 
263
 
238
   my @decrypted_devices;
264
   my @decrypted_devices;
239
 
265
 
240
   # Decrypt each disk in the list
266
   # Decrypt each disk in the list
241
   foreach my $disk (@{$diskList}) {
267
   foreach my $disk (@{$geliConfig->{'diskList'}}) {
242
      unless ( -e $disk ) {
268
      unless ( -e $disk ) {
243
         logMsg "Disk $disk does not exist\n";
269
         logMsg "Disk $disk does not exist\n";
244
         return '';
270
         return '';
245
      }
271
      }
246
 
272
 
247
      # Derive the decrypted device name (.eli suffix on FreeBSD)
273
      # Derive the decrypted device name (.eli suffix on FreeBSD)
248
      my $decrypted = $disk . '.eli';
274
      my $decrypted = $disk . '.eli';
249
 
275
 
250
      # Decrypt using geli attach with the keyfile
276
      # Decrypt using geli attach with the keyfile
251
      logMsg("Decrypting $disk with keyfile $keyfile");
277
      logMsg("Decrypting $disk with keyfile $keyfile");
252
      if ( my $result = system('geli', 'attach', '-k', $keyfile, $disk) == 0 ) {
278
      if ( my $result = system('geli', 'attach', '-k', $geliConfig->{'target'}, $disk) == 0 ) {
253
         logMsg "Failed to decrypt $disk (exit $result)\n";
279
         logMsg "Failed to decrypt $disk (exit $result)\n";
254
         return '';
280
         next; # ignore failed disks and continue to see if we can import the pool
255
      }
281
      }
256
 
282
 
257
      unless ( -e $decrypted ) {
283
      unless ( -e $decrypted ) {
258
         logMsg "Decrypted device $decrypted does not exist after geli attach\n";
284
         logMsg "Decrypted device $decrypted does not exist after geli attach\n";
259
         return '';
285
         return '';
Line 263... Line 289...
263
 
289
 
264
   # Import the ZFS pool
290
   # Import the ZFS pool
265
   logMsg("Importing ZFS pool $poolname");
291
   logMsg("Importing ZFS pool $poolname");
266
   my @import_cmd = ('zpool', 'import');
292
   my @import_cmd = ('zpool', 'import');
267
   # If decrypted devices exist, add their directories to -d list
293
   # If decrypted devices exist, add their directories to -d list
268
   foreach my $dev (@decrypted_devices) {
294
   #foreach my $dev (@decrypted_devices) {
269
      my $dir = $dev;
295
   #   my $dir = $dev;
270
      $dir =~ s!/[^/]+$!!;  # Remove filename to get directory
296
   #   $dir =~ s!/[^/]+$!!;  # Remove filename to get directory
271
      push @import_cmd, '-d', $dir;
297
   #   push @import_cmd, '-d', $dir;
272
   }
298
   #}
-
 
299
   
273
   push @import_cmd, $poolname;
300
   push @import_cmd, $poolname;
274
 
301
 
275
   my $result = system(@import_cmd);
302
   my $result = system(@import_cmd);
276
   unless ( $result == 0 ) {
303
   unless ( $result == 0 ) {
277
      logMsg("Failed to import zfs pool $poolname (exit $result)\n");
304
      logMsg("Failed to import zfs pool $poolname (exit $result)\n");