[pve-devel] [PATCH manager 1/2] api: ceph: deprecate pools in favor or pool
Fabian Grünbichler
f.gruenbichler at proxmox.com
Mon Mar 20 09:31:50 CET 2023
On December 9, 2022 1:58 pm, Aaron Lauterer wrote:
> /nodes/{node}/ceph/pools/{pool} returns the pool details right away on a
> GET. This makes it bad practice to add additional sub API endpoints.
>
> By deprecating it and replacing it with /nodes/{node}/ceph/pool/{pool}
> (singular instead of plural) we can turn that into an index GET
> response, making it possible to expand it more in the future.
>
> The GET call returning the pool details is moved into
> /nodes/{node}/ceph/pool/{pool}/status
>
> The code in the new Pool.pm is basically a copy of Pools.pm to avoid
> a close coupling with the old code as it is possible that it will divert
> until we can entirely remove the old code.
>
> Signed-off-by: Aaron Lauterer <a.lauterer at proxmox.com>
high level: pveceph also should be switched to the new endpoints ;)
two small nits inline..
> ---
> The next step is to add a pool/{name}/namespace API so that we can list
> available namespaces and maybe also manage them via the API/UI in the
> future.
>
> PVE/API2/Ceph.pm | 7 +
> PVE/API2/Ceph/Makefile | 1 +
> PVE/API2/Ceph/Pool.pm | 801 +++++++++++++++++++++++++++++++++++++++++
> PVE/API2/Ceph/Pools.pm | 11 +-
> 4 files changed, 815 insertions(+), 5 deletions(-)
> create mode 100644 PVE/API2/Ceph/Pool.pm
>
> diff --git a/PVE/API2/Ceph.pm b/PVE/API2/Ceph.pm
> index f3442408..946aebd3 100644
> --- a/PVE/API2/Ceph.pm
> +++ b/PVE/API2/Ceph.pm
> @@ -23,6 +23,7 @@ use PVE::API2::Ceph::FS;
> use PVE::API2::Ceph::MDS;
> use PVE::API2::Ceph::MGR;
> use PVE::API2::Ceph::MON;
> +use PVE::API2::Ceph::Pool;
> use PVE::API2::Ceph::Pools;
> use PVE::API2::Storage::Config;
>
> @@ -55,6 +56,12 @@ __PACKAGE__->register_method ({
> path => 'fs',
> });
>
> +__PACKAGE__->register_method ({
> + subclass => "PVE::API2::Ceph::Pool",
> + path => 'pool',
> +});
> +
> +# TODO: deprecrated, remove with PVE 8
> __PACKAGE__->register_method ({
> subclass => "PVE::API2::Ceph::Pools",
> path => 'pools',
> diff --git a/PVE/API2/Ceph/Makefile b/PVE/API2/Ceph/Makefile
> index 45daafda..5d6f642b 100644
> --- a/PVE/API2/Ceph/Makefile
> +++ b/PVE/API2/Ceph/Makefile
> @@ -5,6 +5,7 @@ PERLSOURCE= \
> MON.pm \
> OSD.pm \
> FS.pm \
> + Pool.pm \
> Pools.pm \
> MDS.pm
>
> diff --git a/PVE/API2/Ceph/Pool.pm b/PVE/API2/Ceph/Pool.pm
> new file mode 100644
> index 00000000..cd46311b
> --- /dev/null
> +++ b/PVE/API2/Ceph/Pool.pm
> @@ -0,0 +1,801 @@
> +package PVE::API2::Ceph::Pool;
> +
> +use strict;
> +use warnings;
> +
> +use PVE::Ceph::Tools;
> +use PVE::Ceph::Services;
> +use PVE::JSONSchema qw(get_standard_option parse_property_string);
> +use PVE::RADOS;
> +use PVE::RESTHandler;
> +use PVE::RPCEnvironment;
> +use PVE::Storage;
> +use PVE::Tools qw(extract_param);
> +
> +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) {
> + $data->{$p->{pool_name}} = $p;
> + }
> +
> + return $data;
> +};
> +
> +
> +__PACKAGE__->register_method ({
> + name => 'lspools',
> + path => '',
> + method => 'GET',
> + description => "List all pools.",
and their settings (which are settable by the POST/PUT endpoints).
> + proxyto => 'node',
> + protected => 1,
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
> + },
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + },
> + },
> + returns => {
> + type => 'array',
> + items => {
> + type => "object",
> + properties => {
> + pool => {
> + type => 'integer',
> + title => 'ID',
> + },
> + pool_name => {
> + type => 'string',
> + title => 'Name',
> + },
> + size => {
> + type => 'integer',
> + title => 'Size',
> + },
> + type => {
> + type => 'string',
> + title => 'Type',
> + enum => ['replicated', 'erasure', 'unknown'],
> + },
> + 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,
> + },
> + application_metadata => {
> + type => 'object',
> + title => 'Associated Applications',
> + optional => 1,
> + },
> + },
> + },
> + links => [ { rel => 'child', href => "{pool_name}" } ],
> + },
> + code => sub {
> + my ($param) = @_;
> +
> + PVE::Ceph::Tools::check_ceph_inited();
> +
> + my $rados = PVE::RADOS->new();
> +
> + my $stats = {};
> + my $res = $rados->mon_command({ prefix => 'df' });
> +
> + foreach my $d (@{$res->{pools}}) {
> + next if !$d->{stats};
> + next if !defined($d->{id});
> + $stats->{$d->{id}} = $d->{stats};
> + }
> +
> + $res = $rados->mon_command({ prefix => 'osd dump' });
> + my $rulestmp = $rados->mon_command({ prefix => 'osd crush rule dump'});
> +
> + my $rules = {};
> + for my $rule (@$rulestmp) {
> + $rules->{$rule->{rule_id}} = $rule->{rule_name};
> + }
> +
> + my $data = [];
> + my $attr_list = [
> + 'pool',
> + 'pool_name',
> + 'size',
> + 'min_size',
> + 'pg_num',
> + 'crush_rule',
> + 'pg_autoscale_mode',
> + 'application_metadata',
> + ];
> +
> + # 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}};
> + }
> +
> + if (my $s = $stats->{$d->{pool}}) {
> + $d->{bytes_used} = $s->{bytes_used};
> + $d->{percent_used} = $s->{percent_used};
> + }
> +
> + # Cephs numerical pool types are barely documented. Found the following in the Ceph
> + # codebase: https://github.com/ceph/ceph/blob/ff144995a849407c258bcb763daa3e03cfce5059/src/osd/osd_types.h#L1221-L1233
> + if ($e->{type} == 1) {
> + $d->{type} = 'replicated';
> + } elsif ($e->{type} == 3) {
> + $d->{type} = 'erasure';
> + } else {
> + # we should never get here, but better be safe
> + $d->{type} = 'unknown';
> + }
> + push @$data, $d;
> + }
> +
> +
> + return $data;
> + }});
> +
> +
> +my $ceph_pool_common_options = sub {
> + my ($nodefault) = shift;
> + my $options = {
> + name => {
> + title => 'Name',
> + description => "The name of the pool. It must be unique.",
> + type => 'string',
> + },
> + size => {
> + title => 'Size',
> + description => 'Number of replicas per object',
> + type => 'integer',
> + default => 3,
> + optional => 1,
> + minimum => 1,
> + maximum => 7,
> + },
> + min_size => {
> + title => 'Min Size',
> + description => 'Minimum number of replicas per object',
> + type => 'integer',
> + default => 2,
> + optional => 1,
> + minimum => 1,
> + maximum => 7,
> + },
> + pg_num => {
> + title => 'PG Num',
> + description => "Number of placement groups.",
> + type => 'integer',
> + default => 128,
> + optional => 1,
> + minimum => 1,
> + 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.",
> + type => 'string',
> + optional => 1,
> + },
> + application => {
> + title => 'Application',
> + description => "The application of the pool.",
> + default => 'rbd',
> + type => 'string',
> + enum => ['rbd', 'cephfs', 'rgw'],
> + optional => 1,
> + },
> + pg_autoscale_mode => {
> + title => 'PG Autoscale Mode',
> + description => "The automatic PG scaling mode of the pool.",
> + type => 'string',
> + enum => ['on', 'off', 'warn'],
> + 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) {
> + delete $options->{$_}->{default} for keys %$options;
> + }
> + return $options;
> +};
> +
> +
> +my $add_storage = sub {
> + my ($pool, $storeid, $ec_data_pool) = @_;
> +
> + my $storage_params = {
> + type => 'rbd',
> + pool => $pool,
> + storage => $storeid,
> + krbd => 0,
> + content => 'rootdir,images',
> + };
> +
> + $storage_params->{'data-pool'} = $ec_data_pool if $ec_data_pool;
> +
> + PVE::API2::Storage::Config->create($storage_params);
> +};
> +
> +my $get_storages = sub {
> + my ($pool) = @_;
> +
> + my $cfg = PVE::Storage::config();
> +
> + my $storages = $cfg->{ids};
> + my $res = {};
> + foreach my $storeid (keys %$storages) {
> + my $curr = $storages->{$storeid};
> + next if $curr->{type} ne 'rbd';
> + $curr->{pool} = 'rbd' if !defined $curr->{pool}; # set default
> + if (
> + $pool eq $curr->{pool} ||
> + (defined $curr->{'data-pool'} && $pool eq $curr->{'data-pool'})
> + ) {
> + $res->{$storeid} = $storages->{$storeid};
> + }
> + }
> +
> + return $res;
> +};
> +
> +my $ec_format = {
> + k => {
> + type => 'integer',
> + description => "Number of data chunks. Will create an erasure coded pool plus a"
> + ." replicated pool for metadata.",
> + minimum => 2,
> + },
> + m => {
> + type => 'integer',
> + description => "Number of coding chunks. Will create an erasure coded pool plus a"
> + ." replicated pool for metadata.",
> + minimum => 1,
> + },
> + 'failure-domain' => {
> + type => 'string',
> + description => "CRUSH failure domain. Default is 'host'. Will create an erasure"
> + ." coded pool plus a replicated pool for metadata.",
> + format_description => 'domain',
> + optional => 1,
> + default => 'host',
> + },
> + 'device-class' => {
> + type => 'string',
> + description => "CRUSH device class. Will create an erasure coded pool plus a"
> + ." replicated pool for metadata.",
> + format_description => 'class',
> + optional => 1,
> + },
> + profile => {
> + description => "Override the erasure code (EC) profile to use. Will create an"
> + ." erasure coded pool plus a replicated pool for metadata.",
> + type => 'string',
> + format_description => 'profile',
> + optional => 1,
> + },
> +};
> +
> +sub ec_parse_and_check {
> + my ($property, $rados) = @_;
> + return if !$property;
> +
> + my $ec = parse_property_string($ec_format, $property);
> +
> + die "Erasure code profile '$ec->{profile}' does not exist.\n"
> + if $ec->{profile} && !PVE::Ceph::Tools::ecprofile_exists($ec->{profile}, $rados);
> +
> + return $ec;
> +}
> +
> +
> +__PACKAGE__->register_method ({
> + name => 'createpool',
> + path => '',
> + method => 'POST',
> + description => "Create Ceph pool",
> + proxyto => 'node',
> + protected => 1,
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Modify' ]],
> + },
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + add_storages => {
> + description => "Configure VM and CT storage using the new pool.",
> + type => 'boolean',
> + optional => 1,
> + default => "0; for erasure coded pools: 1",
> + },
> + 'erasure-coding' => {
> + description => "Create an erasure coded pool for RBD with an accompaning"
> + ." replicated pool for metadata storage. With EC, the common ceph options 'size',"
> + ." 'min_size' and 'crush_rule' parameters will be applied to the metadata pool.",
> + type => 'string',
> + format => $ec_format,
> + optional => 1,
> + },
> + %{ $ceph_pool_common_options->() },
> + },
> + },
> + returns => { type => 'string' },
> + code => sub {
> + my ($param) = @_;
> +
> + PVE::Cluster::check_cfs_quorum();
> + PVE::Ceph::Tools::check_ceph_configured();
> +
> + my $pool = my $name = extract_param($param, 'name');
> + my $node = extract_param($param, 'node');
> + my $add_storages = extract_param($param, 'add_storages');
> +
> + 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);
> + }
> +
> + my $rados = PVE::RADOS->new();
> + my $ec = ec_parse_and_check(extract_param($param, 'erasure-coding'), $rados);
> + $add_storages = 1 if $ec && !defined($add_storages);
> +
> + if ($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);
> + }
> +
> + # pool defaults
> + $param->{pg_num} //= 128;
> + $param->{size} //= 3;
> + $param->{min_size} //= 2;
> + $param->{application} //= 'rbd';
> + $param->{pg_autoscale_mode} //= 'warn';
> +
> + my $worker = sub {
> + # reopen with longer timeout
> + $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
> +
> + if ($ec) {
> + if (!$ec->{profile}) {
> + $ec->{profile} = PVE::Ceph::Tools::get_ecprofile_name($pool, $rados);
> + eval {
> + PVE::Ceph::Tools::create_ecprofile(
> + $ec->@{'profile', 'k', 'm', 'failure-domain', 'device-class'},
> + $rados,
> + );
> + };
> + die "could not create erasure code profile '$ec->{profile}': $@\n" if $@;
> + print "created new erasure code profile '$ec->{profile}'\n";
> + }
> +
> + my $ec_data_param = {};
> + # copy all params, should be a flat hash
> + $ec_data_param = { map { $_ => $param->{$_} } keys %$param };
> +
> + $ec_data_param->{pool_type} = 'erasure';
> + $ec_data_param->{allow_ec_overwrites} = 'true';
> + $ec_data_param->{erasure_code_profile} = $ec->{profile};
> + delete $ec_data_param->{size};
> + delete $ec_data_param->{min_size};
> + delete $ec_data_param->{crush_rule};
> +
> + # metadata pool should be ok with 32 PGs
> + $param->{pg_num} = 32;
> +
> + $pool = "${name}-metadata";
> + $ec->{data_pool} = "${name}-data";
> +
> + PVE::Ceph::Tools::create_pool($ec->{data_pool}, $ec_data_param, $rados);
> + }
> +
> + PVE::Ceph::Tools::create_pool($pool, $param, $rados);
> +
> + if ($add_storages) {
> + eval { $add_storage->($pool, "${name}", $ec->{data_pool}) };
> + die "adding PVE storage for ceph pool '$name' failed: $@\n" if $@;
> + }
> + };
> +
> + return $rpcenv->fork_worker('cephcreatepool', $pool, $user, $worker);
> + }});
> +
> +
> +__PACKAGE__->register_method ({
> + name => 'destroypool',
> + path => '{name}',
> + method => 'DELETE',
> + description => "Destroy pool",
> + proxyto => 'node',
> + protected => 1,
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Modify' ]],
> + },
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + name => {
> + description => "The name of the pool. It must be unique.",
> + type => 'string',
> + },
> + force => {
> + description => "If true, destroys pool even if in use",
> + type => 'boolean',
> + optional => 1,
> + default => 0,
> + },
> + remove_storages => {
> + description => "Remove all pveceph-managed storages configured for this pool",
> + type => 'boolean',
> + optional => 1,
> + default => 0,
> + },
> + remove_ecprofile => {
> + description => "Remove the erasure code profile. Defaults to true, if applicable.",
> + type => 'boolean',
> + optional => 1,
> + default => 1,
> + },
> + },
> + },
> + returns => { type => 'string' },
> + code => sub {
> + my ($param) = @_;
> +
> + PVE::Ceph::Tools::check_ceph_inited();
> +
> + my $rpcenv = PVE::RPCEnvironment::get();
> + my $user = $rpcenv->get_user();
> + $rpcenv->check($user, '/storage', ['Datastore.Allocate'])
> + if $param->{remove_storages};
> +
> + my $pool = $param->{name};
> +
> + my $worker = sub {
> + my $storages = $get_storages->($pool);
> +
> + # if not forced, destroy ceph pool only when no
> + # vm disks are on it anymore
> + if (!$param->{force}) {
> + my $storagecfg = PVE::Storage::config();
> + foreach my $storeid (keys %$storages) {
> + my $storage = $storages->{$storeid};
> +
> + # check if any vm disks are on the pool
> + print "checking storage '$storeid' for RBD images..\n";
> + my $res = PVE::Storage::vdisk_list($storagecfg, $storeid);
> + die "ceph pool '$pool' still in use by storage '$storeid'\n"
> + if @{$res->{$storeid}} != 0;
> + }
> + }
> + my $rados = PVE::RADOS->new();
> +
> + my $pool_properties = PVE::Ceph::Tools::get_pool_properties($pool, $rados);
> +
> + PVE::Ceph::Tools::destroy_pool($pool, $rados);
> +
> + if (my $ecprofile = $pool_properties->{erasure_code_profile}) {
> + print "found erasure coded profile '$ecprofile', destroying its CRUSH rule\n";
> + my $crush_rule = $pool_properties->{crush_rule};
> + eval { PVE::Ceph::Tools::destroy_crush_rule($crush_rule, $rados); };
> + warn "removing crush rule '${crush_rule}' failed: $@\n" if $@;
> +
> + if ($param->{remove_ecprofile} // 1) {
> + print "destroying erasure coded profile '$ecprofile'\n";
> + eval { PVE::Ceph::Tools::destroy_ecprofile($ecprofile, $rados) };
> + warn "removing EC profile '${ecprofile}' failed: $@\n" if $@;
> + }
> + }
> +
> + if ($param->{remove_storages}) {
> + my $err;
> + foreach my $storeid (keys %$storages) {
> + # skip external clusters, not managed by pveceph
> + next if $storages->{$storeid}->{monhost};
> + eval { PVE::API2::Storage::Config->delete({storage => $storeid}) };
> + if ($@) {
> + warn "failed to remove storage '$storeid': $@\n";
> + $err = 1;
> + }
> + }
> + die "failed to remove (some) storages - check log and remove manually!\n"
> + if $err;
> + }
> + };
> + return $rpcenv->fork_worker('cephdestroypool', $pool, $user, $worker);
> + }});
> +
> +
> +__PACKAGE__->register_method ({
> + name => 'setpool',
> + path => '{name}',
> + method => 'PUT',
> + description => "Change POOL settings",
> + proxyto => 'node',
> + protected => 1,
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Modify' ]],
> + },
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + %{ $ceph_pool_common_options->('nodefault') },
> + },
> + },
> + returns => { type => 'string' },
> + code => sub {
> + my ($param) = @_;
> +
> + PVE::Ceph::Tools::check_ceph_configured();
> +
> + my $rpcenv = PVE::RPCEnvironment::get();
> + my $authuser = $rpcenv->get_user();
> +
> + 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);
> + };
> +
> + return $rpcenv->fork_worker('cephsetpool', $pool, $authuser, $worker);
> + }});
> +
> +__PACKAGE__->register_method ({
> + name => 'poolindex',
> + path => '{name}',
> + method => 'GET',
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
> + },
> + description => "Pool index.",
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + name => {
> + description => 'The name of the pool.',
> + type => 'string',
> + },
> + },
> + },
> + returns => {
> + type => 'array',
> + items => {
> + type => "object",
> + properties => {},
> + },
> + links => [ { rel => 'child', href => "{name}" } ],
> + },
> + code => sub {
> + my ($param) = @_;
> +
> + my $result = [
> + { name => 'status' },
> + ];
> +
> + return $result;
> + }});
> +
> +
> +__PACKAGE__->register_method ({
> + name => 'getpool',
> + path => '{name}/status',
> + method => 'GET',
> + description => "List pool settings.",
whereas this actually returns *much more* than just the settings, and is
therefor rightly named "status", so maybe the description should also make that
clear ;)
> + proxyto => 'node',
> + protected => 1,
> + permissions => {
> + check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
> + },
> + parameters => {
> + additionalProperties => 0,
> + properties => {
> + node => get_standard_option('pve-node'),
> + name => {
> + description => "The name of the pool. It must be unique.",
> + type => 'string',
> + },
> + verbose => {
> + type => 'boolean',
> + default => 0,
> + optional => 1,
> + description => "If enabled, will display additional data".
> + "(eg. statistics).",
> + },
> + },
> + },
> + returns => {
> + type => "object",
> + properties => {
> + id => { type => 'integer', title => 'ID' },
> + pgp_num => { type => 'integer', title => 'PGP num' },
> + noscrub => { type => 'boolean', title => 'noscrub' },
> + 'nodeep-scrub' => { type => 'boolean', title => 'nodeep-scrub' },
> + nodelete => { type => 'boolean', title => 'nodelete' },
> + nopgchange => { type => 'boolean', title => 'nopgchange' },
> + nosizechange => { type => 'boolean', title => 'nosizechange' },
> + write_fadvise_dontneed => { type => 'boolean', title => 'write_fadvise_dontneed' },
> + hashpspool => { type => 'boolean', title => 'hashpspool' },
> + use_gmt_hitset => { type => 'boolean', title => 'use_gmt_hitset' },
> + 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->() },
> + },
> + },
> + code => sub {
> + my ($param) = @_;
> +
> + PVE::Ceph::Tools::check_ceph_inited();
> +
> + my $verbose = $param->{verbose};
> + my $pool = $param->{name};
> +
> + my $rados = PVE::RADOS->new();
> + my $res = $rados->mon_command({
> + prefix => 'osd pool get',
> + pool => "$pool",
> + var => 'all',
> + });
> +
> + my $data = {
> + id => $res->{pool_id},
> + name => $pool,
> + 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},
> + noscrub => "$res->{noscrub}",
> + 'nodeep-scrub' => "$res->{'nodeep-scrub'}",
> + nodelete => "$res->{nodelete}",
> + nopgchange => "$res->{nopgchange}",
> + nosizechange => "$res->{nosizechange}",
> + write_fadvise_dontneed => "$res->{write_fadvise_dontneed}",
> + 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";
> + $data->{statistics} = $d->{stats};
> + }
> +
> + my $apps = $rados->mon_command({ prefix => "osd pool application get", pool => "$pool", });
> + $data->{application_list} = [ keys %$apps ];
> + }
> +
> + return $data;
> + }});
> +
> +
> +1;
> diff --git a/PVE/API2/Ceph/Pools.pm b/PVE/API2/Ceph/Pools.pm
> index fce56787..ffae73b9 100644
> --- a/PVE/API2/Ceph/Pools.pm
> +++ b/PVE/API2/Ceph/Pools.pm
> @@ -1,4 +1,5 @@
> package PVE::API2::Ceph::Pools;
> +# TODO: Deprecated, drop with PVE 8.0! PVE::API2::Ceph::Pool is the replacement
>
> use strict;
> use warnings;
> @@ -37,7 +38,7 @@ __PACKAGE__->register_method ({
> name => 'lspools',
> path => '',
> method => 'GET',
> - description => "List all pools.",
> + description => "List all pools. Deprecated, please use `/nodes/{node}/ceph/pool`.",
> proxyto => 'node',
> protected => 1,
> permissions => {
> @@ -393,7 +394,7 @@ __PACKAGE__->register_method ({
> name => 'createpool',
> path => '',
> method => 'POST',
> - description => "Create Ceph pool",
> + description => "Create Ceph pool. Deprecated, please use `/nodes/{node}/ceph/pool`.",
> proxyto => 'node',
> protected => 1,
> permissions => {
> @@ -509,7 +510,7 @@ __PACKAGE__->register_method ({
> name => 'destroypool',
> path => '{name}',
> method => 'DELETE',
> - description => "Destroy pool",
> + description => "Destroy pool. Deprecated, please use `/nodes/{node}/ceph/pool/{name}`.",
> proxyto => 'node',
> protected => 1,
> permissions => {
> @@ -615,7 +616,7 @@ __PACKAGE__->register_method ({
> name => 'setpool',
> path => '{name}',
> method => 'PUT',
> - description => "Change POOL settings",
> + description => "Change POOL settings. Deprecated, please use `/nodes/{node}/ceph/pool/{name}`.",
> proxyto => 'node',
> protected => 1,
> permissions => {
> @@ -658,7 +659,7 @@ __PACKAGE__->register_method ({
> name => 'getpool',
> path => '{name}',
> method => 'GET',
> - description => "List pool settings.",
> + description => "List pool settings. Deprecated, please use `/nodes/{node}/ceph/pool/{pool}/status`.",
> proxyto => 'node',
> protected => 1,
> permissions => {
> --
> 2.30.2
>
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
>
More information about the pve-devel
mailing list