From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 20A04628F9 for ; Tue, 24 Nov 2020 11:58:26 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1C8F8AA3E for ; Tue, 24 Nov 2020 11:58:26 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id B1823A7C1 for ; Tue, 24 Nov 2020 11:58:17 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 7824940967 for ; Tue, 24 Nov 2020 11:58:17 +0100 (CET) From: Alwin Antreich To: pve-devel@lists.proxmox.com Date: Tue, 24 Nov 2020 11:58:04 +0100 Message-Id: <20201124105811.1416723-2-a.antreich@proxmox.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201124105811.1416723-1-a.antreich@proxmox.com> References: <20201124105811.1416723-1-a.antreich@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.016 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [pools.pm, ceph.pm, pveceph.pm, mon.pm, osd.pm, mds.pm, fs.pm] Subject: [pve-devel] [PATCH manager v2 1/8] api: ceph: subclass pools X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Nov 2020 10:58:26 -0000 for better handling and since the pool endpoints got more entries. Signed-off-by: Alwin Antreich --- PVE/API2/Ceph/Makefile | 1 + PVE/API2/Ceph.pm | 380 +------------------------------------- PVE/API2/Ceph/POOLS.pm | 404 +++++++++++++++++++++++++++++++++++++++++ PVE/CLI/pveceph.pm | 9 +- 4 files changed, 416 insertions(+), 378 deletions(-) create mode 100644 PVE/API2/Ceph/POOLS.pm diff --git a/PVE/API2/Ceph/Makefile b/PVE/API2/Ceph/Makefile index 5b6493d5..65c7b862 100644 --- a/PVE/API2/Ceph/Makefile +++ b/PVE/API2/Ceph/Makefile @@ -5,6 +5,7 @@ PERLSOURCE= \ MON.pm \ OSD.pm \ FS.pm \ + POOLS.pm \ MDS.pm all: diff --git a/PVE/API2/Ceph.pm b/PVE/API2/Ceph.pm index c3a3091d..8e7e525e 100644 --- a/PVE/API2/Ceph.pm +++ b/PVE/API2/Ceph.pm @@ -20,6 +20,7 @@ use PVE::Tools qw(run_command file_get_contents file_set_contents); use PVE::API2::Ceph::OSD; use PVE::API2::Ceph::FS; +use PVE::API2::Ceph::POOLS; use PVE::API2::Ceph::MDS; use PVE::API2::Ceph::MGR; use PVE::API2::Ceph::MON; @@ -54,6 +55,11 @@ __PACKAGE__->register_method ({ path => 'fs', }); +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Ceph::POOLS", + path => 'pools', +}); + __PACKAGE__->register_method ({ name => 'index', path => '', @@ -239,35 +245,6 @@ __PACKAGE__->register_method ({ return $res; }}); -my $add_storage = sub { - my ($pool, $storeid) = @_; - - my $storage_params = { - type => 'rbd', - pool => $pool, - storage => $storeid, - krbd => 0, - content => 'rootdir,images', - }; - - 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}; - $res->{$storeid} = $storages->{$storeid} - if $curr->{type} eq 'rbd' && $pool eq $curr->{pool}; - } - - return $res; -}; __PACKAGE__->register_method ({ name => 'init', @@ -583,227 +560,6 @@ __PACKAGE__->register_method ({ return PVE::Ceph::Tools::ceph_cluster_status(); }}); -__PACKAGE__->register_method ({ - name => 'lspools', - path => 'pools', - method => 'GET', - description => "List all pools.", - 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' }, - 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' }, - }, - }, - 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', - ]; - - foreach my $e (@{$res->{pools}}) { - my $d = {}; - foreach my $attr (@$attr_list) { - $d->{$attr} = $e->{$attr} if defined($e->{$attr}); - } - - 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}; - } - push @$data, $d; - } - - - return $data; - }}); - - -my $ceph_pool_common_options = sub { - my ($nodefault) = shift; - my $options = { - name => { - description => "The name of the pool. It must be unique.", - type => 'string', - }, - size => { - description => 'Number of replicas per object', - type => 'integer', - default => 3, - optional => 1, - minimum => 1, - maximum => 7, - }, - min_size => { - description => 'Minimum number of replicas per object', - type => 'integer', - default => 2, - optional => 1, - minimum => 1, - maximum => 7, - }, - pg_num => { - description => "Number of placement groups.", - type => 'integer', - default => 128, - optional => 1, - minimum => 8, - maximum => 32768, - }, - crush_rule => { - description => "The rule to use for mapping object placement in the cluster.", - type => 'string', - optional => 1, - }, - application => { - description => "The application of the pool.", - default => 'rbd', - type => 'string', - enum => ['rbd', 'cephfs', 'rgw'], - optional => 1, - }, - pg_autoscale_mode => { - description => "The automatic PG scaling mode of the pool.", - type => 'string', - enum => ['on', 'off', 'warn'], - default => 'warn', - optional => 1, - }, - }; - - if ($nodefault) { - delete $options->{$_}->{default} for keys %$options; - } - return $options; -}; - - -__PACKAGE__->register_method ({ - name => 'createpool', - path => 'pools', - method => 'POST', - description => "Create 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, - }, - %{ $ceph_pool_common_options->() }, - }, - }, - returns => { type => 'string' }, - code => sub { - my ($param) = @_; - - PVE::Cluster::check_cfs_quorum(); - PVE::Ceph::Tools::check_ceph_configured(); - - my $pool = $param->{name}; - my $rpcenv = PVE::RPCEnvironment::get(); - my $user = $rpcenv->get_user(); - - if ($param->{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'; - - my $worker = sub { - - PVE::Ceph::Tools::create_pool($pool, $ceph_param); - - if ($param->{add_storages}) { - my $err; - eval { $add_storage->($pool, "${pool}"); }; - if ($@) { - warn "failed to add storage: $@"; - $err = 1; - } - die "adding storage for pool '$pool' failed, check log and add manually!\n" - if $err; - } - }; - - return $rpcenv->fork_worker('cephcreatepool', $pool, $user, $worker); - }}); my $possible_flags = PVE::Ceph::Tools::get_possible_osd_flags(); my $possible_flags_list = [ sort keys %$possible_flags ]; @@ -913,130 +669,6 @@ __PACKAGE__->register_method ({ return undef; }}); -__PACKAGE__->register_method ({ - name => 'destroypool', - path => 'pools/{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, - }, - }, - }, - 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; - } - } - - PVE::Ceph::Tools::destroy_pool($pool); - - 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 => 'pools/{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 = $param->{name}; - my $ceph_param = \%$param; - for my $item ('name', 'node') { - # not ceph parameters - delete $ceph_param->{$item}; - } - - my $worker = sub { - PVE::Ceph::Tools::set_pool($pool, $ceph_param); - }; - - return $rpcenv->fork_worker('cephsetpool', $pool, $authuser, $worker); - }}); - __PACKAGE__->register_method ({ name => 'crush', diff --git a/PVE/API2/Ceph/POOLS.pm b/PVE/API2/Ceph/POOLS.pm new file mode 100644 index 00000000..744f2bce --- /dev/null +++ b/PVE/API2/Ceph/POOLS.pm @@ -0,0 +1,404 @@ +package PVE::API2::Ceph::POOLS; + +use strict; +use warnings; + +use PVE::Ceph::Tools; +use PVE::Ceph::Services; +use PVE::JSONSchema qw(get_standard_option); +use PVE::RADOS; +use PVE::RESTHandler; +use PVE::RPCEnvironment; +use PVE::Storage; + +use PVE::API2::Storage::Config; + +use base qw(PVE::RESTHandler); + +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 => { + description => 'Number of replicas per object', + title => 'Size', + type => 'integer', + default => 3, + optional => 1, + minimum => 1, + maximum => 7, + }, + min_size => { + description => 'Minimum number of replicas per object', + title => 'Min Size', + type => 'integer', + default => 2, + optional => 1, + minimum => 1, + maximum => 7, + }, + pg_num => { + description => "Number of placement groups.", + title => 'PG Num', + type => 'integer', + default => 128, + optional => 1, + minimum => 8, + maximum => 32768, + }, + crush_rule => { + description => "The rule to use for mapping object placement in the cluster.", + title => 'Crush Rule Name', + type => 'string', + optional => 1, + }, + application => { + description => "The application of the pool.", + title => 'Application', + default => 'rbd', + type => 'string', + enum => ['rbd', 'cephfs', 'rgw'], + optional => 1, + }, + pg_autoscale_mode => { + description => "The automatic PG scaling mode of the pool.", + title => 'PG Autoscale Mode', + type => 'string', + enum => ['on', 'off', 'warn'], + default => 'warn', + optional => 1, + }, + }; + + if ($nodefault) { + delete $options->{$_}->{default} for keys %$options; + } + return $options; +}; + +my $add_storage = sub { + my ($pool, $storeid) = @_; + + my $storage_params = { + type => 'rbd', + pool => $pool, + storage => $storeid, + krbd => 0, + content => 'rootdir,images', + }; + + 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}; + $res->{$storeid} = $storages->{$storeid} + if $curr->{type} eq 'rbd' && $pool eq $curr->{pool}; + } + + return $res; +}; + + +__PACKAGE__->register_method ({ + name => 'lspools', + path => '', + method => 'GET', + description => "List all pools.", + 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' }, + 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' }, + }, + }, + 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', + ]; + + foreach my $e (@{$res->{pools}}) { + my $d = {}; + foreach my $attr (@$attr_list) { + $d->{$attr} = $e->{$attr} if defined($e->{$attr}); + } + + 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}; + } + push @$data, $d; + } + + + return $data; + }}); + + +# FIXME: use pools/{pool_name} with PVE 7.0 +__PACKAGE__->register_method ({ + name => 'createpool', + path => '', + method => 'POST', + description => "Create 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, + }, + %{ $ceph_pool_common_options->() }, + }, + }, + returns => { type => 'string' }, + code => sub { + my ($param) = @_; + + PVE::Cluster::check_cfs_quorum(); + PVE::Ceph::Tools::check_ceph_configured(); + + my $pool = $param->{name}; + my $rpcenv = PVE::RPCEnvironment::get(); + my $user = $rpcenv->get_user(); + + if ($param->{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'; + + my $worker = sub { + + PVE::Ceph::Tools::create_pool($pool, $ceph_param); + + if ($param->{add_storages}) { + my $err; + eval { $add_storage->($pool, "${pool}"); }; + if ($@) { + warn "failed to add storage: $@"; + $err = 1; + } + die "adding storage for pool '$pool' failed, check log and add manually!\n" + if $err; + } + }; + + 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, + }, + }, + }, + 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; + } + } + + PVE::Ceph::Tools::destroy_pool($pool); + + 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 = $param->{name}; + my $ceph_param = \%$param; + for my $item ('name', 'node') { + # not ceph parameters + delete $ceph_param->{$item}; + } + + my $worker = sub { + PVE::Ceph::Tools::set_pool($pool, $ceph_param); + }; + + return $rpcenv->fork_worker('cephsetpool', $pool, $authuser, $worker); + }}); + + +1; diff --git a/PVE/CLI/pveceph.pm b/PVE/CLI/pveceph.pm index 3d7bf2b1..69421ca6 100755 --- a/PVE/CLI/pveceph.pm +++ b/PVE/CLI/pveceph.pm @@ -21,6 +21,7 @@ use PVE::Ceph::Tools; use PVE::Ceph::Services; use PVE::API2::Ceph; use PVE::API2::Ceph::FS; +use PVE::API2::Ceph::POOLS; use PVE::API2::Ceph::MDS; use PVE::API2::Ceph::MGR; use PVE::API2::Ceph::MON; @@ -178,7 +179,7 @@ __PACKAGE__->register_method ({ our $cmddef = { init => [ 'PVE::API2::Ceph', 'init', [], { node => $nodename } ], pool => { - ls => [ 'PVE::API2::Ceph', 'lspools', [], { node => $nodename }, sub { + ls => [ 'PVE::API2::Ceph::POOLS', 'lspools', [], { node => $nodename }, sub { my ($data, $schema, $options) = @_; PVE::CLIFormatter::print_api_result($data, $schema, [ @@ -193,9 +194,9 @@ our $cmddef = { ], $options); }, $PVE::RESTHandler::standard_output_options], - create => [ 'PVE::API2::Ceph', 'createpool', ['name'], { node => $nodename }], - destroy => [ 'PVE::API2::Ceph', 'destroypool', ['name'], { node => $nodename } ], - set => [ 'PVE::API2::Ceph', 'setpool', ['name'], { node => $nodename } ], + create => [ 'PVE::API2::Ceph::POOLS', 'createpool', ['name'], { node => $nodename }], + destroy => [ 'PVE::API2::Ceph::POOLS', 'destroypool', ['name'], { node => $nodename } ], + set => [ 'PVE::API2::Ceph::POOLS', 'setpool', ['name'], { node => $nodename } ], }, lspools => { alias => 'pool ls' }, createpool => { alias => 'pool create' }, -- 2.27.0