mirror of
https://git.proxmox.com/git/pve-installer
synced 2025-04-28 10:32:12 +00:00
proxmox: add zfs module for retrieving importable zpool info
Will be used for prompting the user to rename existing "rpool" ZFS pools, similar to what we do for an existing LVM "pve" volume group. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> Reviewed-by: Aaron Lauterer <a.lauterer@proxmox.com> Tested-by: Aaron Lauterer <a.lauterer@proxmox.com> [ TL: added a bit context for what this will be used and merge in the tests into this preparatory commit ] Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
f39ce7ba56
commit
5443b7049e
@ -17,6 +17,7 @@ PERL_MODULES=\
|
||||
Sys/File.pm \
|
||||
Sys/Net.pm \
|
||||
Sys/Udev.pm \
|
||||
Sys/ZFS.pm \
|
||||
UI.pm \
|
||||
UI/Base.pm \
|
||||
UI/Gtk3.pm \
|
||||
|
93
Proxmox/Sys/ZFS.pm
Normal file
93
Proxmox/Sys/ZFS.pm
Normal file
@ -0,0 +1,93 @@
|
||||
package Proxmox::Sys::ZFS;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Proxmox::Sys::Command qw(run_command);
|
||||
|
||||
use base qw(Exporter);
|
||||
our @EXPORT_OK = qw(get_exported_pools);
|
||||
|
||||
# Parses the output of running `zpool import`, which shows all importable
|
||||
# ZFS pools.
|
||||
# Unfortunately, `zpool` does not support JSON or any other machine-readable
|
||||
# format for output, so we have to do it the hard way.
|
||||
#
|
||||
# Example output of `zpool import` looks like this:
|
||||
#
|
||||
# root@proxmox:/# zpool import
|
||||
# pool: testpool
|
||||
# id: 4958685680270539150
|
||||
# state: ONLINE
|
||||
# action: The pool can be imported using its name or numeric identifier.
|
||||
# config:
|
||||
#
|
||||
# testpool ONLINE
|
||||
# vdc ONLINE
|
||||
# vdd ONLINE
|
||||
#
|
||||
# pool: rpool
|
||||
# id: 9412322616744093413
|
||||
# state: ONLINE
|
||||
# status: The pool was last accessed by another system.
|
||||
# action: The pool can be imported using its name or numeric identifier and
|
||||
# the '-f' flag.
|
||||
# see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-EY
|
||||
# config:
|
||||
#
|
||||
# rpool ONLINE
|
||||
# mirror-0 ONLINE
|
||||
# vda3 ONLINE
|
||||
# vdb3 ONLINE
|
||||
#
|
||||
sub zpool_import_parse_output {
|
||||
my ($fh) = @_;
|
||||
|
||||
my $pools = []; # all found pools
|
||||
my $pool = {}; # last found pool in output
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
# first, if we find the start of a new pool, add it to the list with
|
||||
# its name
|
||||
if ($line =~ /^\s+pool: (.+)$/) {
|
||||
# push the previous parsed pool to the result list
|
||||
push @$pools, $pool if %$pool;
|
||||
$pool = { name => $1 };
|
||||
next;
|
||||
}
|
||||
|
||||
# ignore any (garbage) output before the actual list, just in case
|
||||
next if !%$pool;
|
||||
|
||||
# add any possibly-useful attribute to the last (aka. current) pool
|
||||
if ($line =~ /^\s*(id|state|status|action): (.+)$/) {
|
||||
chomp($pool->{$1} = $2);
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
# add the final parsed pool to the list
|
||||
push @$pools, $pool if %$pool;
|
||||
return $pools;
|
||||
}
|
||||
|
||||
# Returns an array of all importable ZFS pools on the system.
|
||||
# Each entry is a hash of the format:
|
||||
#
|
||||
# {
|
||||
# name => '<pool name>',
|
||||
# id => <numeric pool-id>,
|
||||
# /* see also zpool_state_to_name() in lib/libzfs/libzfs_pool.c /*
|
||||
# state => 'OFFLINE' | 'REMOVED' | 'FAULTED' | 'SPLIT' | 'UNAVAIL' \
|
||||
# | 'FAULTED' | 'DEGRADED' | 'ONLINE',
|
||||
# status => '<human-readable status string>', optional
|
||||
# action => '<human-readable action string>', optional
|
||||
# }
|
||||
sub get_exported_pools {
|
||||
my $raw = run_command(['zpool', 'import']);
|
||||
open (my $fh, '<', \$raw) or die 'failed to open in-memory stream';
|
||||
|
||||
return zpool_import_parse_output($fh);
|
||||
}
|
||||
|
||||
1;
|
@ -3,12 +3,13 @@ all:
|
||||
export PERLLIB=..
|
||||
|
||||
.PHONY: check
|
||||
check: test-zfs-arc-max test-run-command test-parse-fqdn test-ui2-stdio
|
||||
check: test-zfs-arc-max test-run-command test-parse-fqdn test-ui2-stdio test-zfs-get-pool-list
|
||||
|
||||
.PHONY: test-zfs-arc-max
|
||||
test-zfs-arc-max:
|
||||
./zfs-arc-max.pl
|
||||
|
||||
.PHONY: test-run-command
|
||||
test-run-command:
|
||||
./run-command.pl
|
||||
|
||||
@ -19,3 +20,7 @@ test-parse-fqdn:
|
||||
.PHONY: test-ui2-stdio
|
||||
test-ui2-stdio:
|
||||
./ui2-stdio.pl
|
||||
|
||||
.PHONY: test-zfs-get-pool-list
|
||||
test-zfs-get-pool-list:
|
||||
./zfs-get-pool-list.pl
|
||||
|
57
test/zfs-get-pool-list.pl
Executable file
57
test/zfs-get-pool-list.pl
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Temp;
|
||||
use Test::More tests => 8;
|
||||
|
||||
use Proxmox::Sys::ZFS;
|
||||
use Proxmox::UI;
|
||||
|
||||
my $log_file = File::Temp->new();
|
||||
Proxmox::Log::init($log_file->filename);
|
||||
|
||||
Proxmox::UI::init_stdio();
|
||||
|
||||
our $ZPOOL_IMPORT_TEST_OUTPUT = <<EOT;
|
||||
pool: testpool
|
||||
id: 4958685680270539150
|
||||
state: ONLINE
|
||||
action: The pool can be imported using its name or numeric identifier.
|
||||
config:
|
||||
|
||||
testpool ONLINE
|
||||
vdc ONLINE
|
||||
vdd ONLINE
|
||||
|
||||
pool: rpool
|
||||
id: 9412322616744093413
|
||||
state: FAULTED
|
||||
status: The pool was last accessed by another system.
|
||||
action: The pool can be imported using its name or numeric identifier and
|
||||
the '-f' flag.
|
||||
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-EY
|
||||
config:
|
||||
|
||||
rpool ONLINE
|
||||
mirror-0 ONLINE
|
||||
vda3 ONLINE
|
||||
vdb3 ONLINE
|
||||
EOT
|
||||
|
||||
my $pools = {
|
||||
testpool => { id => '4958685680270539150', state => 'ONLINE' },
|
||||
rpool => { id => '9412322616744093413', state => 'FAULTED' },
|
||||
};
|
||||
|
||||
open(my $fh, '<', \$ZPOOL_IMPORT_TEST_OUTPUT);
|
||||
my $result = Proxmox::Sys::ZFS::zpool_import_parse_output($fh);
|
||||
while (my ($name, $info) = each %$pools) {
|
||||
my ($p) = grep { $_->{name} eq $name } @$result;
|
||||
ok(defined($p), "pool $name was found");
|
||||
is($p->{id}, $info->{id}, "pool $name has correct id");
|
||||
is($p->{state}, $info->{state}, "pool $name has correct state");
|
||||
like($p->{action}, qr/^The pool can be imported using its name or numeric identifier/,
|
||||
"pool $name can be imported");
|
||||
}
|
Loading…
Reference in New Issue
Block a user