Last active
November 21, 2020 13:27
-
-
Save pruiz/5d7fbd75efb413ac15d2d0e3ef54f32a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
## Proxmox's ZFSPoolPlugin patch allowing dynamic guessing of pool name. | |
## | |
## Description: | |
## Needed on clusters composed of nodes with mixed ZFS layouts, | |
## where pool names do not match across all cluster' nodes. | |
## | |
## This extends/overrides default ZFSPoolPlugin allowing declaration | |
## of 'pool' property at storage.cfg like: | |
## 1) Using a coma separated list, so each item will be tried in order. | |
## 2) Using '$auto' in order to lookup a pool with pve:id=$storeid. | |
## | |
## Version: 1.0 | |
## Author: Pablo Ruiz García <pablo.ruiz@gmail.com> | |
## | |
package PVE::Storage::Custom::ZFSPoolPluginEx; | |
use strict; | |
use warnings; | |
use IO::File; | |
use POSIX; | |
use PVE::Tools qw(run_command); | |
use PVE::Storage::Plugin; | |
use PVE::Storage::ZFSPoolPlugin; | |
use PVE::RPCEnvironment; | |
use Data::Dumper; | |
use base qw(PVE::Storage::ZFSPoolPlugin); | |
# Configuration | |
sub type { | |
return 'zfspool'; | |
} | |
sub api { | |
return 5; | |
} | |
sub register { | |
my ($class) = @_; | |
my $type = $class->type(); | |
my $pdata = 'PVE::Storage::Plugin'->private(); | |
# Remove default ZFSPoolPlugin, so we can override it | |
delete $pdata->{plugins}->{$type}; | |
delete $pdata->{plugindata}->{$type}; | |
$class->SUPER::register(); | |
} | |
sub zfs_pool_is_valid { | |
my ($class, $pool) = @_; | |
my $name = undef; | |
eval { | |
$name = $class->zfs_get_properties(undef, 'name', $pool); | |
}; | |
return defined($name) && $name eq $pool; | |
} | |
sub zfs_find_by_id { | |
my ($class, $id) = @_; | |
my $result = undef; | |
my @params = ('-t', 'filesystem', '-o', 'name,pve:id'); | |
my $output = $class->zfs_request(undef, undef, 'list', @params); | |
if ($output) | |
{ | |
my @lines = sort(split /\n/, $output); | |
foreach my $line (@lines) { | |
my ($name, $pveid) = split(/\s+/, $line); | |
next if ($pveid ne $id); | |
# XXX: Skip nested datasets/volumes.. | |
next if (defined($result) && rindex($result, $name)); | |
die "multiple zfs datasets with pve:id=$id found?!\n" if defined($result); | |
$result = $name; | |
} | |
} | |
return $result; | |
} | |
sub check_value { | |
my ($class, $type, $key, $value, $storeid, $skipSchemaCheck) = @_; | |
# if pool is a list, let's try each pool | |
# in order, first one found/existing, wins. | |
if ($key eq "pool" && index($value, ",")) { | |
foreach my $pool (split /,/, $value) { | |
$pool = PVE::Tools::trim($pool); | |
if ($class->zfs_pool_is_valid($pool)) { | |
$value = $pool; | |
last; | |
} | |
} | |
} | |
# if pool is magic keyword '$auto', we need to | |
# search for a dataset with pve:id=$storeid. | |
if ($key eq "pool" && $value eq "\$auto") { | |
$value = $class->zfs_find_by_id($storeid) // $value; | |
} | |
return $class->SUPER::check_value($type, $key, $value, $storeid, $skipSchemaCheck); | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment