[pve-devel] [PATCH v3 storage 1/2] Fix #1542: show storage utilization per pool

Dietmar Maurer dietmar at proxmox.com
Thu Apr 12 12:48:40 CEST 2018


comments inline.

> On April 11, 2018 at 4:36 PM Alwin Antreich <a.antreich at proxmox.com> wrote:
> 
> 
>  - get the percent_used value for a ceph pool and
>    calculate it where ceph doesn't supply it (pre kraken)
>  - use librados2-perl for pool status
>  - add librados2-perl as build-depends and depends in debian/control
> 
> Signed-off-by: Alwin Antreich <a.antreich at proxmox.com>
> ---
>  PVE/CLI/pvesm.pm         |  1 +
>  PVE/Storage.pm           |  4 +-
>  PVE/Storage/RBDPlugin.pm | 96
> ++++++++++++++++++++++++++++++++++++++----------
>  debian/control           |  2 +
>  4 files changed, 81 insertions(+), 22 deletions(-)
> 
> diff --git a/PVE/CLI/pvesm.pm b/PVE/CLI/pvesm.pm
> index 5774364..98cd9e9 100755
> --- a/PVE/CLI/pvesm.pm
> +++ b/PVE/CLI/pvesm.pm
> @@ -149,6 +149,7 @@ my $print_status = sub {
>  	my $active = $res->{active} ? 'active' : 'inactive';
>  	my ($per, $per_fmt) = (0, '% 7.2f%%');
>  	$per = ($res->{used}*100)/$res->{total} if $res->{total} > 0;
> +	$per = $res->{percent_used} if defined($res->{percent_used});
>  
>  	if (!$res->{enabled}) {
>  	    $per = 'N/A';
> diff --git a/PVE/Storage.pm b/PVE/Storage.pm
> index 4140a99..0d9d7cf 100755
> --- a/PVE/Storage.pm
> +++ b/PVE/Storage.pm
> @@ -1065,14 +1065,14 @@ sub storage_info {
>  	    next;
>  	}
>  
> -	my ($total, $avail, $used, $active);
> -	eval { ($total, $avail, $used, $active) = $plugin->status($storeid, $scfg,
> $cache); };
> +	my ($total, $avail, $used, $active, $percent_used) = eval {
> $plugin->status($storeid, $scfg, $cache); };
>  	warn $@ if $@;
>  	next if !$active;
>  	$info->{$storeid}->{total} = int($total);
>  	$info->{$storeid}->{avail} = int($avail);
>  	$info->{$storeid}->{used} = int($used);
>  	$info->{$storeid}->{active} = $active;
> +	$info->{$storeid}->{percent_used} = $percent_used if
> (defined($percent_used));
>      }
>  
>      return $info;
> diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm
> index fd5a2ef..1b09b58 100644
> --- a/PVE/Storage/RBDPlugin.pm
> +++ b/PVE/Storage/RBDPlugin.pm
> @@ -7,6 +7,7 @@ use Net::IP;
>  use PVE::Tools qw(run_command trim);
>  use PVE::Storage::Plugin;
>  use PVE::JSONSchema qw(get_standard_option);
> +use PVE::RADOS;
>  
>  use base qw(PVE::Storage::Plugin);
>  
> @@ -90,6 +91,50 @@ my $rados_cmd = sub {
>      return $build_cmd->('/usr/bin/rados', $scfg, $storeid, $op, @options);
>  };
>  
> +my $ceph_connect_option = sub {
> +    my ($scfg, $storeid, %options) = @_;
> +
> +    my $cmd_option = {};
> +    my $ceph_storeid_conf = "/etc/pve/priv/ceph/${storeid}.conf";
> +    my $keyring = "/etc/pve/priv/ceph/${storeid}.keyring";
> +    my $pveceph_managed = !defined($scfg->{monhost});
> +
> +    $cmd_option->{ceph_conf} = $pveceph_config if (-e $pveceph_config);
> +
> +    if (-e $ceph_storeid_conf) {
> +	if ($pveceph_managed) {
> +	    warn "ignoring custom ceph config for storage '$storeid', 'monhost' is
> not set (assuming pveceph managed cluster)!\n";
> +	} else {
> +	    $cmd_option->{ceph_conf} = $ceph_storeid_conf;
> +	}
> +    }
> +
> +    $cmd_option->{keyring} = $keyring if (-e $keyring);
> +    $cmd_option->{auth_supported} = (defined $cmd_option->{keyring}) ?
> 'cephx' : 'none';
> +    $cmd_option->{userid} =  $scfg->{username} ? $scfg->{username} : 'admin';
> +    $cmd_option->{mon_host} = $hostlist->($scfg->{monhost}, ',') if
> (defined($scfg->{monhost}));
> +
> +    if (%options) {
> +	foreach my $k (keys %options) {
> +	    $cmd_option->{$k} = $options{$k};
> +	}
> +    }
> +
> +
> +    return $cmd_option;
> +
> +};
> +
> +my $librados_connect = sub {
> +    my ($scfg, $storeid, $options) = @_;
> +
> +    my $librados_config = $ceph_connect_option->($scfg, $storeid);
> +
> +    my $rados = PVE::RADOS->new(%$librados_config);
> +
> +    return $rados;
> +};
> +
>  # needed for volumes created using ceph jewel (or higher)
>  my $krbd_feature_disable = sub {
>      my ($scfg, $storeid, $name) = @_;
> @@ -539,31 +584,42 @@ sub list_images {
>  sub status {
>      my ($class, $storeid, $scfg, $cache) = @_;
>  
> -    my $cmd = &$rados_cmd($scfg, $storeid, 'df');
> -
> -    my $stats = {};
>  
> -    my $parser = sub {
> -	my $line = shift;
> -	if ($line =~ m/^\s*total(?:\s|_)(\S+)\s+(\d+)(k|M|G|T)?/) {
> -	    $stats->{$1} = $2;
> -	    # luminous has units here..
> -	    if ($3) {
> -		$stats->{$1} *= $rbd_unittobytes->{$3}/1024;
> -	    }
> -	}
> -    };
> +    my $rados = &$librados_connect($scfg, $storeid);
> +    my $df = $rados->mon_command({ prefix => 'df', format => 'json' });
>  
> -    eval {
> -	run_rbd_command($cmd, errmsg => "rados error", errfunc => sub {}, outfunc =>
> $parser);
> -    };
> +    my ($d) = grep { $_->{name} eq $scfg->{pool} } @{$df->{pools}};
>  
> -    my $total = $stats->{space} ? $stats->{space}*1024 : 0;
> -    my $free = $stats->{avail} ? $stats->{avail}*1024 : 0;
> -    my $used = $stats->{used} ? $stats->{used}*1024: 0;
> +    # max_avail -> max available space for data w/o replication in the pool
> +    # bytes_used -> data w/o replication in the pool
> +    # precent_used -> ceph's %-used of the pool
> +    my $free = $d->{stats}->{max_avail};
> +    my $used = $d->{stats}->{bytes_used};
> +    my $percent_used = $d->{stats}->{percent_used};
> +    my $total = $used + $free;
>      my $active = 1;

what if we simply do:

    my $free = $d->{stats}->{max_avail};
    my $used = $d->{stats}->{bytes_used};
    my $total = $used + $free;
    
    if (defined(my $percent_used = $d->{stats}->{percent_used})) {
        $used = ($total * $percent_used) / 100;
        $free = $total - $used;
    }


and discard the code below?

>  
> -    return ($total, $free, $used, $active);
> +    if (!defined($percent_used)) {
> +	my $pg_dump = $rados->mon_command({ prefix => 'pg dump', format => 'json'
> });
> +	my ($pool) = grep { $_->{poolid} eq $d->{id} } @{$pg_dump->{pool_stats}};
> +
> +	# num_object_copies -> holds the count of all object w/ replication of
> +	# the pool
> +	# num_objects_degraded -> holds all degraded object w/ replication of
> +	# the pool
> +	my $pg_num_obj_copies = $pool->{stat_sum}->{num_object_copies};
> +	my $pg_num_obj_degraded = $pool->{stat_sum}->{num_objects_degraded};
> +
> +	# percent_used -> the raw space occupied by bytes_used, reduced by a
> +	# %-factor from the number of degraded objects compared to the total
> +	# number of objects in the pool, the new bytes_used is devided by the
> +	# new max_avail to get the current %-used
> +	my $percent_used_c = $used * (($pg_num_obj_copies - $pg_num_obj_degraded) /
> $pg_num_obj_copies);
> +	$percent_used_c = $percent_used_c / ($percent_used_c + $free);
> +	$percent_used = ($percent_used_c * 100);
> +    }
> +
> +	return ($total, $free, $used, $active, $percent_used);
>  }
>  
>  sub activate_storage {
> diff --git a/debian/control b/debian/control
> index 3f39364..2cf585a 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -5,6 +5,7 @@ Maintainer: Proxmox Support Team <support at proxmox.com>
>  Build-Depends: debhelper (>= 7.0.50~),
>                 libpve-common-perl (>= 5.0-28),
>                 libtest-mockmodule-perl,
> +               librados2-perl,
>                 lintian,
>                 perl (>= 5.10.0-19),
>                 pve-doc-generator,
> @@ -18,6 +19,7 @@ Depends: cstream,
>           libfile-chdir-perl,
>           libnet-dbus-perl,
>           libpve-common-perl (>= 5.0-28),
> +         librados2-perl,
>           lvm2,
>           nfs-common,
>           perl (>= 5.6.0-16),
> -- 
> 2.11.0
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



More information about the pve-devel mailing list