[pve-devel] [PATCH v2 storage 1/2] Fix #1542: show storage utilization per pool
Alwin Antreich
a.antreich at proxmox.com
Mon Apr 9 18:26:44 CEST 2018
- 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 | 98 ++++++++++++++++++++++++++++++++++++------------
debian/control | 2 +
4 files changed, 78 insertions(+), 27 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..62c1933 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) = @_;
@@ -160,7 +205,7 @@ sub run_rbd_command {
*STDERR->flush();
};
}
-
+
eval { run_command($cmd, %args); };
if (my $err = $@) {
die $errmsg . $lasterr if length($lasterr);
@@ -200,7 +245,7 @@ sub rbd_ls {
my $err = $@;
die $err if $err && $err !~ m/doesn't contain rbd images/ ;
-
+
return $list;
}
@@ -425,7 +470,7 @@ sub clone_image {
my ($vtype, $basename, $basevmid, undef, undef, $isBase) =
$class->parse_volname($volname);
- die "$volname is not a base image and snapname is not provided\n"
+ die "$volname is not a base image and snapname is not provided\n"
if !$isBase && !length($snapname);
my $name = &$find_free_diskname($storeid, $scfg, $vmid);
@@ -444,7 +489,7 @@ sub clone_image {
my $newvol = "$basename/$name";
$newvol = $name if length($snapname);
- my $cmd = &$rbd_cmd($scfg, $storeid, 'clone', &$add_pool_to_disk($scfg, $basename),
+ my $cmd = &$rbd_cmd($scfg, $storeid, 'clone', &$add_pool_to_disk($scfg, $basename),
'--snap', $snap, &$add_pool_to_disk($scfg, $name));
run_rbd_command($cmd, errmsg => "rbd clone '$basename' error");
@@ -532,38 +577,41 @@ sub list_images {
push @$res, $info;
}
}
-
+
return $res;
}
sub status {
my ($class, $storeid, $scfg, $cache) = @_;
- my $cmd = &$rados_cmd($scfg, $storeid, 'df');
- my $stats = {};
+ my $rados = &$librados_connect($scfg, $storeid);
+ my $df = $rados->mon_command({ prefix => 'df', format => 'json' });
- 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;
- }
- }
- };
-
- 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;
+ 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;
- 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 of the pool
+ # (object + replicas), while num_objects_degraded holds all degraded
+ # objects (object + replicas)
+ my $pg_num_obj_copies = $pool->{stat_sum}->{num_object_copies};
+ my $pg_num_obj_degraded = $pool->{stat_sum}->{num_objects_degraded};
+
+ 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
More information about the pve-devel
mailing list