This patch adds a new API endpoint that returns a list of included guests, their volumes and whether they are included in a backup.
The output is formatted to be used with the extJS tree panel. Signed-off-by: Aaron Lauterer <a.laute...@proxmox.com> --- v1 -> v2: * simplified the code * refactored according to feedback from fabian [1] The call to PVE::VZDump->get_included_guests($job) will definitely change as that patch need another version [0] [0] https://pve.proxmox.com/pipermail/pve-devel/2020-April/042795.html [1] https://pve.proxmox.com/pipermail/pve-devel/2020-January/041361.html PVE/API2/Backup.pm | 176 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/PVE/API2/Backup.pm b/PVE/API2/Backup.pm index 86377c0a..685a196c 100644 --- a/PVE/API2/Backup.pm +++ b/PVE/API2/Backup.pm @@ -324,4 +324,180 @@ __PACKAGE__->register_method({ die "$@" if ($@); }}); +__PACKAGE__->register_method({ + name => 'get_volume_backup_included', + path => '{id}/included_volumes', + method => 'GET', + protected => 1, + description => "Returns included guests and the backup status of their disks. Optimized to be used in ExtJS tree views.", + permissions => { + check => ['perm', '/', ['Sys.Audit']], + }, + parameters => { + additionalProperties => 0, + properties => { + id => $vzdump_job_id_prop + }, + }, + returns => { + type => 'object', + 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.', + }, + 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'], + }, + 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}; + } + 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)}; + + # 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); + $not_all_permissions = 1 if !$allowed && !$job->{all}; + $allowed; + } @vmids; + + my $result = { + children => [], + leaf => 0, + not_all_permissions => $not_all_permissions, + }; + + foreach (@vmids) { + my $id = $_; + + # 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, + children => [], + leaf => 0, + }; + + my $type = $vmlist->{ids}->{$id}->{type}; + my $node = $vmlist->{ids}->{$id}->{node}; + + my $conf; + my $volumes; + my $name = ""; + + if ($type eq 'qemu') { + $conf = PVE::QemuConfig->load_config($id, $node); + $volumes = PVE::QemuConfig->get_backup_volumes($conf); + $name = $conf->{name}; + } elsif ($type eq 'lxc') { + $conf = PVE::LXC::Config->load_config($id, $node); + $volumes = PVE::LXC::Config->get_backup_volumes($conf); + $name = $conf->{hostname}; + } else { + die "VMID $id is neither Qemu nor LXC guest\n"; + } + + $guest->{name} = $name; + $guest->{type} = $type; + + foreach my $volume (@$volumes) { + my $disk = { + # id field must be unique for ExtJS + id => "$id:$volume->{key}", + name => $volume->{data}->{file} // $volume->{data}->{volume}, + included=> $volume->{included}, + reason => $volume->{reason}, + leaf => 1, + }; + push @{$guest->{children}}, $disk; + } + + # it's possible for a guest to have no volumes configured + $guest->{leaf} = 1 if !@{$guest->{children}}; + + push @{$result->{children}}, $guest; + } + + return $result; + }}); + 1; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel