comments inline

On 11/24/20 11:58 AM, Alwin Antreich wrote:
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.

i'd rather have this as its own patch than here but ok...


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;
+

would it not better to return a hash with mapping
poolname -> data_for_that_pool
?

this way you only need to iterate once? and save
iterations below....

};
+
__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};
+           }

namely here.

you could do then

$d->{autoscale_status} = $autoscale->{$e->{pool}}

or something like that, instead of iterating over the lists
everytime (this is n^2 of number of pools)

+
            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)) {

this is wrong, what if i give '--add_storages 0' ?

            $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)) {

same here

                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

s/avialable/available/

+           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);
+}

don't we have something like this in PVE::Tools?

+
  1;




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

Reply via email to