]> git.proxmox.com Git - pve-manager.git/commitdiff
ceph: add autoscale_status to api calls
authorAlwin Antreich <a.antreich@proxmox.com>
Tue, 20 Apr 2021 08:15:15 +0000 (10:15 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 20 Apr 2021 16:20:35 +0000 (18:20 +0200)
the properties target_size_ratio, target_size_bytes and pg_num_min are
used to fine-tune the pg_autoscaler and are set on a pool. The updated
pool list shows now autoscale settings & status. Including the new
(optimal) target PGs. To make it easier for new users to get/set the
correct amount of PGs.

Signed-off-by: Alwin Antreich <a.antreich@proxmox.com>
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
PVE/API2/Ceph/Pools.pm
PVE/CLI/pveceph.pm

index 01c11100fb0cc9a8d0222d5c4d8252df6d5c8056..014e6be7fb394b6dffdbec5f59cd54f94ba21ea6 100644 (file)
@@ -16,6 +16,24 @@ use PVE::API2::Storage::Config;
 
 use base qw(PVE::RESTHandler);
 
+my $get_autoscale_status = sub {
+    my ($rados) = shift;
+
+    $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
+       $data->{$p->{pool_name}} = $p;
+    }
+
+    return $data;
+};
+
+
 __PACKAGE__->register_method ({
     name => 'lspools',
     path => '',
@@ -37,16 +55,21 @@ __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_min        => { type => 'integer', title => 'min. PG Num', optional => 1, },
+               pg_num_final      => { type => 'integer', title => 'Optimal PG Num', optional => 1, },
+               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}" } ],
@@ -86,12 +109,24 @@ __PACKAGE__->register_method ({
            'pg_autoscale_mode',
        ];
 
+       # pg_autoscaler module is not enabled in Nautilus
+       my $autoscale = eval { $get_autoscale_status->($rados) };
+
        foreach my $e (@{$res->{pools}}) {
            my $d = {};
            foreach my $attr (@$attr_list) {
                $d->{$attr} = $e->{$attr} if defined($e->{$attr});
            }
 
+           if ($autoscale) {
+               $d->{autoscale_status} = $autoscale->{$d->{pool_name}};
+               $d->{pg_num_final} = $d->{autoscale_status}->{pg_num_final};
+               # some info is nested under options instead
+               $d->{pg_num_min} = $e->{options}->{pg_num_min};
+               $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}};
            }
@@ -143,6 +178,13 @@ my $ceph_pool_common_options = sub {
            minimum => 8,
            maximum => 32768,
        },
+       pg_num_min => {
+           title => 'min. PG Num',
+           description => "Minimal number of placement groups.",
+           type => 'integer',
+           optional => 1,
+           maximum => 32768,
+       },
        crush_rule => {
            title => 'Crush Rule Name',
            description => "The rule to use for mapping object placement in the cluster.",
@@ -165,6 +207,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) {
@@ -241,6 +296,12 @@ __PACKAGE__->register_method ({
        my $rpcenv = PVE::RPCEnvironment::get();
        my $user = $rpcenv->get_user();
 
+       # Ceph uses target_size_bytes
+       if (defined($param->{'target_size'})) {
+           my $target_sizestr = extract_param($param, 'target_size');
+           $param->{target_size_bytes} = PVE::JSONSchema::parse_size($target_sizestr);
+       }
+
        if ($add_storages) {
            $rpcenv->check($user, '/storage', ['Datastore.Allocate']);
            die "pool name contains characters which are illegal for storage naming\n"
@@ -387,6 +448,12 @@ __PACKAGE__->register_method ({
        my $pool = extract_param($param, 'name');
        my $node = extract_param($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::JSONSchema::parse_size($target_sizestr);
+       }
+
        my $worker = sub {
            PVE::Ceph::Tools::set_pool($pool, $param);
        };
@@ -438,6 +505,7 @@ __PACKAGE__->register_method ({
            fast_read              => { type => 'boolean', title => 'Fast Read' },
            application_list       => { type => 'array', title => 'Application', optional => 1 },
            statistics             => { type => 'object', title => 'Statistics', optional => 1 },
+           autoscale_status       => { type => 'object',  title => 'Autoscale Status', optional => 1 },
            %{ $ceph_pool_common_options->() },
        },
     },
@@ -462,6 +530,7 @@ __PACKAGE__->register_method ({
            size                   => $res->{size},
            min_size               => $res->{min_size},
            pg_num                 => $res->{pg_num},
+           pg_num_min             => $res->{pg_num_min},
            pgp_num                => $res->{pgp_num},
            crush_rule             => $res->{crush_rule},
            pg_autoscale_mode      => $res->{pg_autoscale_mode},
@@ -474,12 +543,19 @@ __PACKAGE__->register_method ({
            hashpspool             => "$res->{hashpspool}",
            use_gmt_hitset         => "$res->{use_gmt_hitset}",
            fast_read              => "$res->{fast_read}",
+           target_size            => $res->{target_size_bytes},
+           target_size_ratio      => $res->{target_size_ratio},
        };
 
        if ($verbose) {
            my $stats;
            my $res = $rados->mon_command({ prefix => 'df' });
 
+           # pg_autoscaler module is not enabled in Nautilus
+           # avoid partial read further down, use new rados instance
+           my $autoscale_status = eval { $get_autoscale_status->() };
+           $data->{autoscale_status} = $autoscale_status->{$pool};
+
            foreach my $d (@{$res->{pools}}) {
                next if !$d->{stats};
                next if !defined($d->{name}) && !$d->{name} ne "$pool";
index ba5067b1ec5ee394c11f4c1330ca63432f70f9b6..4c0008815e2ed679601cfe1271bea0810577b71e 100755 (executable)
@@ -207,7 +207,11 @@ our $cmddef = {
                    'size',
                    'min_size',
                    'pg_num',
+                   'pg_num_min',
+                   'pg_num_final',
                    'pg_autoscale_mode',
+                   'target_size',
+                   'target_size_ratio',
                    'crush_rule_name',
                    'percent_used',
                    'bytes_used',