fix #1895: use json for 'rbd ls -l' and 'rbd info'

since ceph changed the plain output format for 12.2.8
we have to change the code anyway, and when were at it,
we can change it to the (hopefully) more robust json output

Co-authored-by: Alwin Antreich <a.antreich@proxmox.com>
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak
2018-09-06 11:35:42 +02:00
committed by Thomas Lamprecht
parent 361481cfd0
commit 89a8800bc3

View File

@ -9,6 +9,7 @@ use PVE::Storage::Plugin;
use PVE::JSONSchema qw(get_standard_option);
use PVE::RADOS;
use PVE::Storage::CephTools;
use JSON;
use base qw(PVE::Storage::Plugin);
@ -19,6 +20,12 @@ my $rbd_unittobytes = {
"T" => 1024*1024*1024*1024,
};
my $get_parent_image_name = sub {
my ($parent) = @_;
return undef if !$parent;
return $parent->{image} . "@" . $parent->{snapshot};
};
my $add_pool_to_disk = sub {
my ($scfg, $disk) = @_;
@ -82,7 +89,7 @@ my $krbd_feature_disable = sub {
my $krbd_feature_blacklist = ['deep-flatten', 'fast-diff', 'object-map', 'exclusive-lock'];
my (undef, undef, undef, undef, $features) = rbd_volume_info($scfg, $storeid, $name);
my $active_features = { map { $_ => 1 } PVE::Tools::split_list($features)};
my $active_features = { map { $_ => 1 } $features };
my $incompatible_features = join(',', grep { %$active_features{$_} } @$krbd_feature_blacklist);
if ($incompatible_features) {
@ -153,25 +160,13 @@ sub run_rbd_command {
sub rbd_ls {
my ($scfg, $storeid) = @_;
my $cmd = &$rbd_cmd($scfg, $storeid, 'ls', '-l');
my $cmd = &$rbd_cmd($scfg, $storeid, 'ls', '-l', '--format', 'json');
my $pool = $scfg->{pool} ? $scfg->{pool} : 'rbd';
my $list = {};
my $raw = '';
my $parser = sub {
my $line = shift;
if ($line =~ m/^((vm|base)-(\d+)-\S+)\s+(\d+)(k|M|G|T)\s((\S+)\/((vm|base)-\d+-\S+@\S+))?/) {
my ($image, $owner, $size, $unit, $parent) = ($1, $3, $4, $5, $8);
return if $image =~ /@/; #skip snapshots
$list->{$pool}->{$image} = {
name => $image,
size => $size*$rbd_unittobytes->{$unit},
parent => $parent,
vmid => $owner
};
}
$raw .= shift;
};
eval {
@ -180,7 +175,26 @@ sub rbd_ls {
my $err = $@;
die $err if $err && $err !~ m/doesn't contain rbd images/ ;
my $result = $raw ne '' ? JSON::decode_json($raw) : [];
my $list = {};
foreach my $el (@$result) {
next if defined($el->{snapshot});
my $image = $el->{image};
my ($owner) = $image =~ m/^(?:vm|base)-(\d+)-/;
$list->{$pool}->{$image} = {
name => $image,
size => $el->{size},
parent => $get_parent_image_name->($el->{parent}),
vmid => $owner
};
}
return $list;
}
@ -189,38 +203,32 @@ sub rbd_volume_info {
my $cmd = undef;
my @options = ('info', $volname, '--format', 'json');
if($snap){
$cmd = &$rbd_cmd($scfg, $storeid, 'info', $volname, '--snap', $snap);
}else{
$cmd = &$rbd_cmd($scfg, $storeid, 'info', $volname);
push @options, '--snap', $snap;
}
$cmd = &$rbd_cmd($scfg, $storeid, @options);
my $size = undef;
my $parent = undef;
my $format = undef;
my $protected = undef;
my $features = undef;
my $raw = '';
my $parser = sub {
my $line = shift;
if ($line =~ m/size (\d+) (k|M|G|T)B in (\d+) objects/) {
$size = $1 * $rbd_unittobytes->{$2} if ($1);
} elsif ($line =~ m/parent:\s(\S+)\/(\S+)/) {
$parent = $2;
} elsif ($line =~ m/format:\s(\d+)/) {
$format = $1;
} elsif ($line =~ m/protected:\s(\S+)/) {
$protected = 1 if $1 eq "True";
} elsif ($line =~ m/features:\s(.+)/) {
$features = $1;
}
$raw .= shift;
};
run_rbd_command($cmd, errmsg => "rbd error", errfunc => sub {}, outfunc => $parser);
my $volume = $raw ne '' ? JSON::decode_json($raw) : {};
$volume->{parent} = $get_parent_image_name->($volume->{parent});
if (defined($volume->{protected})) {
$volume->{protected} = $volume->{protected} eq "true" ? 1 : undef;
}
return ($size, $parent, $format, $protected, $features);
return $volume->@{qw(size parent format protected features)};
}
# Configuration