the properties target_size_ratio and target_size_bytes are the only two
options by ceph to set on a pool. The updated pool list shows now
autoscale settings & status. Including the new target PGs. To make it
easier for new users to get/set the correct amount of PGs.

And use parameter extraction instead of the unneeded ref copy for params.

Signed-off-by: Alwin Antreich <a.antre...@proxmox.com>
---
 PVE/API2/Ceph/POOLS.pm | 131 +++++++++++++++++++++++++++++++----------
 PVE/CLI/pveceph.pm     |   3 +
 PVE/Ceph/Tools.pm      |  21 +++++++
 3 files changed, 123 insertions(+), 32 deletions(-)

diff --git a/PVE/API2/Ceph/POOLS.pm b/PVE/API2/Ceph/POOLS.pm
index 19fc1b7e..324a1f79 100644
--- a/PVE/API2/Ceph/POOLS.pm
+++ b/PVE/API2/Ceph/POOLS.pm
@@ -3,6 +3,7 @@ package PVE::API2::Ceph::POOLS;
 use strict;
 use warnings;
 
+use PVE::Tools qw(extract_param);
 use PVE::Ceph::Tools;
 use PVE::Ceph::Services;
 use PVE::JSONSchema qw(get_standard_option);
@@ -67,6 +68,19 @@ my $ceph_pool_common_options = sub {
            default => 'warn',
            optional => 1,
        },
+       target_size => {
+           description => "The estimated target size of the pool for the PG 
autoscaler.",
+           title => 'PG Autoscale Target Size',
+           type => 'string',
+           pattern => '(\d+(?:\.\d+)?)([KMGT])?',
+           optional => 1,
+       },
+       target_size_ratio => {
+           description => "The estimated target ratio of the pool for the PG 
autoscaler.",
+           title => 'PG Autoscale Target Ratio',
+           type => 'number',
+           optional => 1,
+       },
     };
 
     if ($nodefault) {
@@ -105,6 +119,30 @@ my $get_storages = sub {
     return $res;
 };
 
+my $get_autoscale_status = sub {
+    my ($rados, $pool) = @_;
+
+    $rados = PVE::RADOS->new() if !defined($rados);
+
+    my $autoscale = $rados->mon_command({
+           prefix => 'osd pool autoscale-status'});
+
+    my $data;
+    foreach my $p (@$autoscale) {
+       $p->{would_adjust} = "$p->{would_adjust}"; # boolean
+       push @$data, $p;
+    }
+
+    if ($pool) {
+       foreach my $p (@$data) {
+           next if $p->{pool_name} ne $pool;
+           $data = $p;
+       }
+    }
+
+    return $data;
+};
+
 
 __PACKAGE__->register_method ({
     name => 'lspools',
@@ -127,16 +165,20 @@ __PACKAGE__->register_method ({
        items => {
            type => "object",
            properties => {
-               pool => { type => 'integer', title => 'ID' },
-               pool_name => { type => 'string', title => 'Name' },
-               size => { type => 'integer', title => 'Size' },
-               min_size => { type => 'integer', title => 'Min Size' },
-               pg_num => { type => 'integer', title => 'PG Num' },
-               pg_autoscale_mode => { type => 'string', optional => 1, title 
=> 'PG Autoscale Mode' },
-               crush_rule => { type => 'integer', title => 'Crush Rule' },
-               crush_rule_name => { type => 'string', title => 'Crush Rule 
Name' },
-               percent_used => { type => 'number', title => '%-Used' },
-               bytes_used => { type => 'integer', title => 'Used' },
+               pool              => { type => 'integer', title => 'ID' },
+               pool_name         => { type => 'string',  title => 'Name' },
+               size              => { type => 'integer', title => 'Size' },
+               min_size          => { type => 'integer', title => 'Min Size' },
+               pg_num            => { type => 'integer', title => 'PG Num' },
+               pg_num_final      => { type => 'integer', title => 'Optimal # 
of PGs' },
+               pg_autoscale_mode => { type => 'string',  title => 'PG 
Autoscale Mode', optional => 1 },
+               crush_rule        => { type => 'integer', title => 'Crush Rule' 
},
+               crush_rule_name   => { type => 'string',  title => 'Crush Rule 
Name' },
+               percent_used      => { type => 'number',  title => '%-Used' },
+               bytes_used        => { type => 'integer', title => 'Used' },
+               target_size       => { type => 'integer', title => 'PG 
Autoscale Target Size', optional => 1 },
+               target_size_ratio => { type => 'number',  title => 'PG 
Autoscale Target Ratio',optional => 1, },
+               autoscale_status  => { type => 'object',  title => 'Autoscale 
Status', optional => 1 },
            },
        },
        links => [ { rel => 'child', href => "{pool_name}" } ],
@@ -176,12 +218,18 @@ __PACKAGE__->register_method ({
            'pg_autoscale_mode',
        ];
 
+       my $autoscale = $get_autoscale_status->($rados);
+
        foreach my $e (@{$res->{pools}}) {
            my $d = {};
            foreach my $attr (@$attr_list) {
                $d->{$attr} = $e->{$attr} if defined($e->{$attr});
            }
 
+           # some info is nested under options instead
+           $d->{target_size} = $e->{options}->{target_size_bytes};
+           $d->{target_size_ratio} = $e->{options}->{target_size_ratio};
+
            if (defined($d->{crush_rule}) && 
defined($rules->{$d->{crush_rule}})) {
                $d->{crush_rule_name} = $rules->{$d->{crush_rule}};
            }
@@ -190,10 +238,17 @@ __PACKAGE__->register_method ({
                $d->{bytes_used} = $s->{bytes_used};
                $d->{percent_used} = $s->{percent_used};
            }
+
+           foreach my $p (@$autoscale) {
+               next if ($p->{pool_id} ne $e->{pool});
+               $d->{autoscale_status} = $p;
+               # pick some info directly from the autoscale_status
+               $d->{pg_num_final} = $p->{pg_num_final};
+           }
+
            push @$data, $d;
        }
 
-
        return $data;
     }});
 
@@ -233,34 +288,37 @@ __PACKAGE__->register_method ({
        PVE::Cluster::check_cfs_quorum();
        PVE::Ceph::Tools::check_ceph_configured();
 
-       my $pool = $param->{name};
+       my $pool = extract_param($param, 'name');
+       my $add_storages = extract_param($param, 'add_storages');
+       delete $param->{node}; # not a ceph option
+
        my $rpcenv = PVE::RPCEnvironment::get();
        my $user = $rpcenv->get_user();
 
-       if ($param->{add_storages}) {
+       # Ceph uses target_size_bytes
+       if (defined($param->{'target_size'})) {
+           my $target_sizestr = extract_param($param, 'target_size');
+           $param->{target_size_bytes} = 
PVE::Ceph::Tools::convert_to_bytes($target_sizestr);
+       }
+
+       if (defined($add_storages)) {
            $rpcenv->check($user, '/storage', ['Datastore.Allocate']);
            die "pool name contains characters which are illegal for storage 
naming\n"
                if !PVE::JSONSchema::parse_storage_id($pool);
        }
 
-       my $ceph_param = \%$param;
-       for my $item ('add_storages', 'name', 'node') {
-           # not ceph parameters
-           delete $ceph_param->{$item};
-       }
-
        # pool defaults
-       $ceph_param->{pg_num} //= 128;
-       $ceph_param->{size} //= 3;
-       $ceph_param->{min_size} //= 2;
-       $ceph_param->{application} //= 'rbd';
-       $ceph_param->{pg_autoscale_mode} //= 'warn';
+       $param->{pg_num} //= 128;
+       $param->{size} //= 3;
+       $param->{min_size} //= 2;
+       $param->{application} //= 'rbd';
+       $param->{pg_autoscale_mode} //= 'warn';
 
        my $worker = sub {
 
-           PVE::Ceph::Tools::create_pool($pool, $ceph_param);
+           PVE::Ceph::Tools::create_pool($pool, $param);
 
-           if ($param->{add_storages}) {
+           if (defined($add_storages)) {
                my $err;
                eval { $add_storage->($pool, "${pool}"); };
                if ($@) {
@@ -391,15 +449,17 @@ __PACKAGE__->register_method ({
        my $rpcenv = PVE::RPCEnvironment::get();
        my $authuser = $rpcenv->get_user();
 
-       my $pool = $param->{name};
-       my $ceph_param = \%$param;
-       for my $item ('name', 'node') {
-           # not ceph parameters
-           delete $ceph_param->{$item};
+       my $pool = extract_param($param, 'name');
+       delete $param->{node};
+
+       # Ceph uses target_size_bytes
+       if (defined($param->{'target_size'})) {
+           my $target_sizestr = extract_param($param, 'target_size');
+           $param->{target_size_bytes} = 
PVE::Ceph::Tools::convert_to_bytes($target_sizestr);
        }
 
        my $worker = sub {
-           PVE::Ceph::Tools::set_pool($pool, $ceph_param);
+           PVE::Ceph::Tools::set_pool($pool, $param);
        };
 
        return $rpcenv->fork_worker('cephsetpool', $pool,  $authuser, $worker);
@@ -448,6 +508,7 @@ __PACKAGE__->register_method ({
            use_gmt_hitset         => { type => 'boolean', title => 
'use_gmt_hitset' },
            fast_read              => { type => 'boolean', title => 'Fast Read' 
},
            statistics             => { type => 'object', title => 
'Statistics', optional => 1 },
+           autoscale_status       => { type => 'object', title => 'Autoscale 
Status', optional => 1 },
            %{ $ceph_pool_common_options->() },
        },
     },
@@ -483,8 +544,12 @@ __PACKAGE__->register_method ({
            hashpspool             => "$res->{hashpspool}",
            use_gmt_hitset         => "$res->{use_gmt_hitset}",
            fast_read              => "$res->{fast_read}",
+           # is only avialable if set
+           target_size            => $res->{target_size_bytes} // undef,
+           target_size_ratio      => $res->{target_size_ratio} // undef,
        };
 
+
        if ($verbose) {
            my $stats;
            my $res = $rados->mon_command({ prefix => 'df' });
@@ -498,6 +563,8 @@ __PACKAGE__->register_method ({
            my $apps = $rados->mon_command({ prefix => "osd pool application 
get", pool => "$pool", });
            my @application = keys %$apps;
            $data->{application} = $application[0];
+
+           $data->{autoscale_status} = $get_autoscale_status->($rados, $pool),
        }
 
        return $data;
diff --git a/PVE/CLI/pveceph.pm b/PVE/CLI/pveceph.pm
index 69421ca6..b7b68540 100755
--- a/PVE/CLI/pveceph.pm
+++ b/PVE/CLI/pveceph.pm
@@ -187,7 +187,10 @@ our $cmddef = {
                    'size',
                    'min_size',
                    'pg_num',
+                   'pg_num_final',
                    'pg_autoscale_mode',
+                   'target_size',
+                   'target_size_ratio',
                    'crush_rule_name',
                    'percent_used',
                    'bytes_used',
diff --git a/PVE/Ceph/Tools.pm b/PVE/Ceph/Tools.pm
index 12d309be..d95e8676 100644
--- a/PVE/Ceph/Tools.pm
+++ b/PVE/Ceph/Tools.pm
@@ -487,4 +487,25 @@ sub ceph_cluster_status {
     return $status;
 }
 
+sub convert_to_bytes {
+    my ($sizestr) = shift;
+
+    die "internal error" if $sizestr !~ m/^(\d+(?:\.\d+)?)([KMGT])?$/;
+    my ($newsize, $unit) = ($1, $2);
+
+    if ($unit) {
+       if ($unit eq 'K') {
+           $newsize = $newsize * 1024;
+       } elsif ($unit eq 'M') {
+           $newsize = $newsize * 1024 * 1024;
+       } elsif ($unit eq 'G') {
+           $newsize = $newsize * 1024 * 1024 * 1024;
+       } elsif ($unit eq 'T') {
+           $newsize = $newsize * 1024 * 1024 * 1024 * 1024;
+       }
+    }
+
+    return int($newsize);
+}
+
 1;
-- 
2.27.0



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to