[pve-devel] [PATCH manager v2 1/8] api: ceph: subclass pools

Dominik Csapak d.csapak at proxmox.com
Tue Nov 24 14:53:20 CET 2020


mhmm.. you did not simply move the code, you added at least the 'titles'
it would be better to have a commit which really only moves the
code to a new file

or at least mention it in the commit message

one comment inline

On 11/24/20 11:58 AM, Alwin Antreich wrote:
> for better handling and since the pool endpoints got more entries.
> 
> Signed-off-by: Alwin Antreich <a.antreich at proxmox.com>
> ---
>   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		\

why POOLS.pm and not Pools.pm ?
the others are only capitalized because they are abbreviations

i'd prefer Pools.pm (but this is debatable...)

>   	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' },
> 






More information about the pve-devel mailing list