[pve-devel] [PATCH storage v2 1/2] fix #1895: use json for 'rbd ls -l' and 'rbd info'

Alwin Antreich a.antreich at proxmox.com
Thu Sep 6 16:07:11 CEST 2018


On Thu, Sep 06, 2018 at 11:35:42AM +0200, Dominik Csapak wrote:
> 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 at proxmox.com>
> Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
> ---
> changes from v1:
> * incorporated the change from alwins patch [1]
> * incorporated thomas feedback:
>  * rename r/l to more meaningful names
>  * check for output of $raw
>  * return hash slice instead of saving the content again
> * refactor parent image name generation
> 
>  PVE/Storage/RBDPlugin.pm | 78 ++++++++++++++++++++++++++----------------------
>  1 file changed, 43 insertions(+), 35 deletions(-)
> 
> diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm
> index be88ad7..6c0e617 100644
> --- a/PVE/Storage/RBDPlugin.pm
> +++ b/PVE/Storage/RBDPlugin.pm
> @@ -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
> -- 
> 2.11.0
With the new code, image names other then our defaults (base-.*/vm-.*)
are not ignored when parsing. This breaks commands like qm rescan.




More information about the pve-devel mailing list