Thursday, August 4, 2011

Renaming user-defined ZFS properties

Here is a short script I cooked up to rename the namespace of all the ZFS user-defined properties on a host. Useful if you need to change com.foo:beans to com.bar:beans for more than a couple of properties on a couple of filesystems.

#!/usr/local/bin/perl

#
# This script looks at the properties for every zfs filesystem and snapshot on
# a server and changes every occurance of a property in in namespace $old to
# namespace $old.
#

use strict;

my ($old, $new) = ("com.foo", "com.bar");
my $overwrite = "yes"; # overwrite existing $new properties
my $localonly = "yes"; # do not move inherited properties

for my $fs ( `zfs list -Ho name` ) {
chomp $fs;
&do_rename($fs);
}

for my $snap ( `zfs list -Ho name -t snapshot` ) {
chomp $snap;
&do_rename($snap);
}

sub do_rename {
#print "Renaming $old to $new on $_[0]\n";
# get list of properties with $old
for my $prop ( `zfs get -Ho property,source,value all $_[0] | grep $old` ) {
$prop =~ m/$old:([a-z._:][a-z.\-_:]*)\t([a-z0-9\/\- ]+)\t(.*)\n/;
#print "Examining property $old:$1 on $_[0] with value $3\n";
my ($suffix, $value) = ($1, $3);
# local check, if enabled
next if (( $localonly eq "yes" ) and ( $2 ne "local" ));
next if (( $overwrite eq "no" ) and ( &check_exists($_[0],"$old:$suffix") == 0 ));
print "Setting $new:$suffix=$value and inheriting (erasing) $old:$suffix on $_[0]\n";
( system("zfs set $new:$suffix=$value $_[0]") == 0 ) or die "Error during zfs set operation";
( system("zfs inherit $old:$suffix $_[0]") == 0 ) or die "Error during zfs inherit operation";
}
}

sub check_exists {
# Return 0 if the specified property [1] exists on object [0]
if ( system("zfs get -Ho value $_[1] $_[0] | grep -qE '^-\$'") == 0 ) {
# DNE
return 1;
} else {
print "$_[1] exists on $_[0]!\n";
return 0;
}
}

No comments:

Post a Comment