[pve-devel] [PATCH manager 3/5] api ceph osd: add volume details endpoint

Aaron Lauterer a.lauterer at proxmox.com
Tue Jul 5 16:19:36 CEST 2022



On 7/5/22 11:58, Thomas Lamprecht wrote:
> Replying here albeit a few things also apply on the 2/5 patch.
> 
> Note that I didn't checked the series as a whole (meaning, full UI and
> backend integration) but noticed a API issues here that has to be fixed
> anyway, so that plus some drive by reviews inline.

I can send a V2 with the suggested changes.

[...]
>>   
>> +__PACKAGE__->register_method ({
>> +    name => 'osdvolume',
>> +    path => '{osdid}/volume',
> 
> adding a API path that isn't returned by any index breaks API schema generation,
> and the UX is also somewhat affected, NAK.
> 
> For this to work the `{osdid}` API call would need to return the sub-paths too
> and set the href property to ensure the API stacks links them and allows to do
> the common completion in pvesh and correct display in the API viewer, among other
> things. But, that'd be naturally ugly too because you need to mix some generated
> data specific to the OSD with some static API path router/schema stuff.
> 
> Instead, please transform {osdid} to a plain GET index call returning only the
> sub routes, and then add a separate sub-route in there for the details endpoint
> from patch 2/5, iow. the end result would be:
> 
> {osdid}/
>      {osdid}/details
>      {osdid}/volume
> 
> Or with slightly changed route path names
> 
> {osdid}/
>      {osdid}/metadata
>      {osdid}/lv-info
> 
> That would also allow to adding further routes in there in the future.
> 

Thanks for the explanation. Will change the API to the latter variant, plus the 
index endpoint for {osdid} itself.

>> +    method => 'GET',
>> +    description => "Get OSD volume details",
>> +    proxyto => 'node',
>> +    protected => 1,
>> +    permissions => {
>> +	check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
> 
> I know we use Datastore.Audit for some other ceph API calls, but that is mostly for
> higher level info about Proxmox VE registered storage clients, to be specific, the docs
> declare it as "view/browse a datastore".
> 
> So I'd like to avoid expanding that usage further, especially for such detailed API
> calls that return a lot of specific system information.
> (same applies for patch 2/3)

Okay, so IIUC, drop the Datastore.Audit and only keep the Sys.Audit?

> 
[...]
>> +	properties => {
>> +	    creation_time => {
>> +		type => 'string',
>> +		description => "Creation time as reported by 'lvs'.",
> 
> I'd use backticks for CLI tools, as this is interpreted by asciidoc too for
> manpage generation.

Will do.
> 
[...]

>> +	my $cmd = ['/usr/sbin/ceph-volume', 'lvm', 'list', '--format', 'json'];
>> +	eval { run_command($cmd, errmsg => 'ceph volume error', outfunc => $parser) };
>> +	die $@ if $@;
> 
> what's the point in eval'ing if you do a plain die then anyway on $@?

Being unsure ;) Looking closer at run_command, it will die if there is some 
issue running the specified command, not found or returning an error. So this 
would only be needed if I would like to catch the error to handle it in some 
way, right?

> 
>> +
>> +	my $result;
>> +	if ($raw =~ m/^(\{.*\})$/s) { #untaint
>> +	    $result = JSON::decode_json($1);
>> +	} else {
>> +	    die "got unexpected data from ceph-volume: '${raw}'\n";
>> +	}
>> +	die "OSD '${osdid}' not found in 'ceph-volume lvm list' on node '${nodename}'\n"
>> +	    if !$result->{$osdid};
>> +
>> +	my $volume_data = {};
>> +	%{$volume_data} = map { $_->{type} => $_ } @{$result->{$osdid}};
> 
> huh? why not just
> 
> my $volume_data = { map { $_->{type} => $_ } @{$result->{$osdid} } };

yeah... missed that when cleaning up the code
> 
>> +	die "volume type '${type}' not found for OSD ${osdid}\n" if !$volume_data->{$type};
>> +
>> +	my $volume = $volume_data->{$type};
> 
> just fyi, we can do a conditional die on variable declaration just fine, compared
> to the always bad conditionally `my $foo = "bar" if $condition` declaration. The former
> isn't touching the conditionality of the declaration (i.e., code will never be executed
> with a unsound value in there), while the latter means that there is an unsound value
> used when the condition evaluates to false.
> 
> E.g., can be fine and sometimes shorter (albeit no hard feelings, I just like to combine
> extraction and error in one, like rust can do much more nicely)
> 
> my $volume = $volume_data->{$type} || die "volume type '${type}' not found for OSD ${osdid}\n"

will change that

> 
>> +
>> +	$raw = '';
>> +	$cmd = ['/sbin/lvs', $volume->{lv_path}, '--reportformat', 'json', '-o', 'lv_time'];
>> +	eval { run_command($cmd, errmsg => 'lvs error', outfunc => $parser) };
>> +	die $@ if $@;
> 
> same as above wrt. probably useless eval
> 
>> +
>> +	if ($raw =~ m/(\{.*\})$/s) { #untaint, lvs has whitespace at beginning
>> +	    $result = JSON::decode_json($1);
>> +	} else {
>> +	    die "got unexpected data from lvs: '${raw}'\n";
>> +	}
>> +	my $data = {};
>> +
>> +	my $keys = [ 'lv_name', 'lv_path', 'lv_uuid', 'vg_name' ];
>> +	for my $key (@$keys) {
>> +	    $data->{$key} = $volume->{$key};
>> +	}
> 
> could avoid about four lines with:
> 
> my $data = { map { $_ => $volume->{$_} } qw(lv_name lv_path lv_uuid vg_name) };
> 
true :)
[...]




More information about the pve-devel mailing list