[pve-devel] [RFC v2 manager 1/5] api: backup: add endpoint to list included guests and volumes
Aaron Lauterer
a.lauterer at proxmox.com
Wed Apr 8 16:29:44 CEST 2020
On 4/7/20 5:55 PM, Thomas Lamprecht wrote:
> On 4/6/20 4:24 PM, Aaron Lauterer wrote:
>> [...]
>> + description => 'Root node of the tree object. Children
represent guests, grandchildren represent volumes of that guest.',
>> + properties => {
>> + not_all_permissions => {
>> + type => 'boolean',
>> + optional => 1,
>> + description => 'Wheter the user is missing permissions to
view all guests.',
>
> s/Wheter/Whether/
thanks for catching that typo
>
>> + },
>> + children => {
>> + type => 'array',
>> + items => {
>> + type => 'object',
>> + properties => {
>> + id => {
>> + type => 'integer',
>> + description => 'VMID of the guest.',
>> + },
>> + name => {
>> + type => 'string',
>> + description => 'Name of the guest',
>> + optional => 1,
>> + },
>> + type => {
>> + type => 'string',
>> + description => 'Type of the guest, VM or CT.',
>> + enum => ['qemu', 'lxc', 'unknown'],
>
> We die in the unknown case, so that cannot be returned
right
>
>> + },
>> + children => {
>> + type => 'array',
>> + optional => 1,
>> + description => 'The volumes of the guest with the
information if they will be included in backups.',
>> + items => {
>> + type => 'object',
>> + properties => {
>> + id => {
>> + type => 'string',
>> + description => 'Configuration key of the volume.',
>> + },
>> + name => {
>> + type => 'string',
>> + description => 'Name of the volume.',
>> + },
>> + included => {
>> + type => 'boolean',
>> + description => 'Wheter the volume is included
in the backup or not.',
>> + },
>> + reason => {
>> + type => 'string',
>> + description => 'The reason why the volume is
included (or excluded).',
>> + },
>> + },
>> + },
>> + },
>> + },
>> + },
>> + },
>> + },
>> + },
>> + code => sub {
>> + my ($param) = @_;
>> +
>> + my $rpcenv = PVE::RPCEnvironment::get();
>> +
>> + my $user = $rpcenv->get_user();
>> +
>> + my $vzconf = cfs_read_file('vzdump.cron');
>> + my $all_jobs = $vzconf->{jobs} || [];
>> + my $job;
>> + my $rrd = PVE::Cluster::rrd_dump();
>> +
>> + foreach my $j (@$all_jobs) {
>> + $job = $j if $j->{id} eq $param->{id};
>
> This could let the reader think that this is a bug, as it looks like
it gets
> overwritten, plus on huge amount of jobs you would iterate a lot of
those for
> nothing, if the $job with the requested id was found early. Rather do:
>
> if ($j->{id} eq $param->{id}) {
> $job = $j;
> last;
> }
>
> This makes it much more explicit and easier to grasp when just
quickly reading over
> the code.
will do
>
>> + }
>> + raise_param_exc({ id => "No such job '$param->{id}'" }) if !$job;
>> +
>> + my $vmlist = PVE::Cluster::get_vmlist();
>> +
>> + my @vmids = @{PVE::VZDump->get_included_guests($job)};
>
> s/vmid/job_vmids/
>
> and the comment on the other series regarding passing this as reference,
> and even as hash.
Yeah, this will be adapted to the changes of the other series, one of
the reasons why this is labeled as RFC
>
>> +
>> + # remove VMIDs to which the user has no permission to not leak
infos
>> + # like the guest name
>> + my $not_all_permissions = 0;
>> + @vmids = grep {
>> + my $allowed = $rpcenv->check($user, "/vms/$_", [
'VM.Backup' ], 1);
>
> hmm, is VM.Backup really the info we want to hide, why not VM.Audit?
> (or those which the user has either permission?)
>
> As VM.Backup is the permission for being allowed to make a backup or
restore one,
> not for being allowed to view a VM in the cluster.
I haven't fully groked the permission system yet. What I want to achieve
is to not show any VMs the user does not have permission to see.
I think VM.Audit should be enough then.
>
>> + $not_all_permissions = 1 if !$allowed && !$job->{all};
>
> This could be found out afterwards, avoids a O(n) expression.
$job->{all} is
> available anyway and if you remember how many elements @vmids had
before you
> can just check if it has less after the permission checking. That has the
> additional advantage that you can omit the $allowed intermediate
variable. For
> example (not fully thought out - so don't just copy 1:1)
>
> my $job_guest_count = scalar(@vmids);
> my @allowed_vmids = grep {
> $rpcenv->check_any($user, "/vms/$_", [ 'VM.Audit', 'VM.Backup' ], 1)
> } @vmids;
>
> my $permissions_for_all = $job->{all} || $job_guest_count ==
scalar(@allowed_vmids);
thx for the hint. I'll look into it.
>
>> + $allowed;
>> + } @vmids;
>> +
>> + my $result = {
>> + children => [],
>> + leaf => 0,
>
> can't that be determined indirectly? I.e., if children is empty? (or
maybe made explicitly undef/null)
I checked the ExtJS docs again and IIUC the leaf flag only needs to be
set if it is true. Thus we can remove it here altogether. But just out
of curiosity; would it be a bad pattern to set it here to the most
likely value (guests usually do have volumes) and check at the end after
all possible volumes are added if there are any children, and if not,
set leaf to 1?
>
>> + not_all_permissions => $not_all_permissions,
>> + };
>> +
>> + foreach (@vmids) {
>> + my $id = $_;
>
> This is a style we normally do not use, do:
>
> for my $vmid (@vmids) {
okay
>
>> +
>> + # it's possible that a job has VMIDs configured that are not in
>> + # vmlist. This could be because a guest was removed but not
purged.
>> + # Since there is no more data available we can only deliver
the VMID
>> + # and no volumes.
>> + if (!defined $vmlist->{ids}->{$id}) {
>> + my $missing_guest = {
>> + id => $id,
>> + type => 'unknown',
>> + leaf => 1,
>> + };
>> + push @{$result->{children}}, $missing_guest;
>> + next;
>> + }
>> +
>> + my $guest = {
>> + id => $id + 0,
>
> here you do + 0 (which i rather have as int($x)) but a few lines
above you don't?
> I'd guess that it isn't required here?
It's possible that I forgot it above but I will check again if it is
stored as a number or string and use int() if needed.
More information about the pve-devel
mailing list