[pve-devel] [PATCH manager 3/6] ceph: add PUT 'flags' api call

Thomas Lamprecht t.lamprecht at proxmox.com
Tue Jul 23 08:04:14 CEST 2019


On 7/22/19 4:08 PM, Dominik Csapak wrote:
> this api call can set multiple flags at once, but does this in a
> worker since this can take quiet some time
> 
> also we only set/unset flags that are not already set/unset (respectively)
> 
> Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
> ---
>  PVE/API2/Ceph.pm | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
> 
> diff --git a/PVE/API2/Ceph.pm b/PVE/API2/Ceph.pm
> index 72cac7e5..9cc6234a 100644
> --- a/PVE/API2/Ceph.pm
> +++ b/PVE/API2/Ceph.pm
> @@ -918,6 +918,71 @@ __PACKAGE__->register_method ({
>  	return $stat->{flags} // '';
>      }});
>  
> +__PACKAGE__->register_method ({
> +    name => 'set_flags',
> +    path => 'flags',
> +    method => 'PUT',
> +    description => "Set/Unset multiple ceph flags at once.",
> +    proxyto => 'node',
> +    protected => 1,
> +    permissions => {
> +	check => ['perm', '/', [ 'Sys.Modify' ]],
> +    },
> +    parameters => {
> +	additionalProperties => 0,
> +	properties => {
> +	    node => get_standard_option('pve-node'),
> +	    %$possible_flags,
> +	},
> +    },
> +    returns => { type => 'string' },
> +    code => sub {
> +	my ($param) = @_;
> +
> +	my $rpcenv = PVE::RPCEnvironment::get();
> +	my $user = $rpcenv->get_user();
> +	PVE::Ceph::Tools::check_ceph_inited();
> +
> +	my $pve_ckeyring_path = PVE::Ceph::Tools::get_config('pve_ckeyring_path');
> +
> +	die "not fully configured - missing '$pve_ckeyring_path'\n"
> +	    if ! -f $pve_ckeyring_path;

I added a new "check_ceph_configured" method which does both, a
ceph_check_inited and the above keyring file check - we had that at
quite a few places. May want to replace above with a call to that in
a v2

> +
> +	my $rados = PVE::RADOS->new();
> +
> +	my $worker = sub {
> +	    # reopen rados object
> +	    my $rados = PVE::RADOS->new();
> +	    my $stat = $rados->mon_command({ prefix => 'osd dump' });
> +	    my $setflags = {};
> +	    map { $setflags->{$_} = 1 } PVE::Tools::split_list($stat->{flags} // '');

can we do something like a 
my $setflags = $stat->{flags} // '';

further above, IMO a bit nicer than those inline, slightly hidden, fall backs.

Also you can then do the map like:
$setflags = { map { $_ => 1 } PVE::Tools::split_list($setflags) };

(no need to set the hash inline, it can create a hash itself)

(or if you do not like the variable reuse prefix the one from rados with e.g.
"_" to underline that they're the same, just another representation)



> +	    my $errors = 0;
> +	    foreach my $flag (sort keys %$possible_flags) {
> +		next if !defined($param->{$flag});

I mean, a possibility would also be to extract the "node" param and then
loop over the remaining param keys. But above is also totally OK, just
an idea.

> +		my $val = $param->{$flag};
> +		my $realflag = $flagmap->{$flag} // $flag;
> +		next if $val && $setflags->{$realflag}; # we do not set already set flags
> +		next if !$val && !$setflags->{$realflag}; # we do not unset not set flags

is a:
next if $val == $setflags->{$realflag}; 
not enough? Both should only be (perl) boolean-like?

> +
> +		my $prefix = $val ? 'set' : 'unset';
> +		eval {
> +		    warn "$prefix $flag\n";

s/warn/print/  ?
I know in the async fork worker both are the same. but in a CLI RPCEnv
they wouldn't be.


> +		    $rados->mon_command({ prefix => "osd $prefix", key => $flag, });
> +		};
> +		if (my $err = $@) {
> +		    warn $err;
> +		    $errors++;
> +		}
> +	    }
> +
> +	    if ($errors) {
> +		die "could not set/unset $errors flags\n";

maybe we could make $errors a hashref and but the actual failed flags in
there, so that a user has better immediate feedback?

> +	    }
> +	};
> +
> +	return $rpcenv->fork_worker('cephsetflags', undef,  $user, $worker);
> +    }});
> +
>  __PACKAGE__->register_method ({
>      name => 'set_flag',
>      path => 'flags/{flag}',
> 





More information about the pve-devel mailing list