From: Filip Schauer <f.schauer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v4 storage 5/6] support moving VMA backups to PBS
Date: Wed, 18 Sep 2024 16:49:52 +0200 [thread overview]
Message-ID: <20240918144953.130780-6-f.schauer@proxmox.com> (raw)
In-Reply-To: <20240918144953.130780-1-f.schauer@proxmox.com>
Extend the move API to support moving VMA backups to a Proxmox Backup
Server.
Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
debian/control | 1 +
src/PVE/API2/Storage/Content.pm | 86 ++++++++++++++++++---------------
src/PVE/Storage/PBSPlugin.pm | 65 +++++++++++++++++++++++++
3 files changed, 112 insertions(+), 40 deletions(-)
diff --git a/debian/control b/debian/control
index d7afa98..6b43557 100644
--- a/debian/control
+++ b/debian/control
@@ -42,6 +42,7 @@ Depends: ceph-common (>= 12.2~),
nfs-common,
proxmox-backup-client (>= 2.1.10~),
proxmox-backup-file-restore,
+ proxmox-vma-to-pbs (>= 0.1.0),
pve-cluster (>= 5.0-32),
smartmontools,
smbclient,
diff --git a/src/PVE/API2/Storage/Content.pm b/src/PVE/API2/Storage/Content.pm
index 4a8fe33..6e38a2e 100644
--- a/src/PVE/API2/Storage/Content.pm
+++ b/src/PVE/API2/Storage/Content.pm
@@ -10,6 +10,7 @@ use File::Copy qw(copy move);
use PVE::SafeSyslog;
use PVE::Cluster;
use PVE::Storage;
+use PVE::Storage::PBSPlugin;
use PVE::INotify;
use PVE::Exception qw(raise_param_exc);
use PVE::RPCEnvironment;
@@ -495,7 +496,7 @@ sub volume_move {
my $source_scfg = PVE::Storage::storage_config($cfg, $source_storeid);
my $source_plugin = PVE::Storage::Plugin->lookup($source_scfg->{type});
- my ($vtype) = $source_plugin->parse_volname($source_volname);
+ my ($vtype, undef, $vmid) = $source_plugin->parse_volname($source_volname);
die "source storage '$source_storeid' does not support volumes of type '$vtype'\n"
if !$source_scfg->{content}->{$vtype};
@@ -522,53 +523,58 @@ sub volume_move {
die "$source_path does not exist" if (!-e $source_path);
my $source_dirname = dirname($source_path);
- die "expected storage '$target_storeid' to be path based\n" if !$target_scfg->{path};
my $target_plugin = PVE::Storage::Plugin->lookup($target_scfg->{type});
- my $target_path = $target_plugin->path($target_scfg, $source_volname, $target_storeid);
-
PVE::Storage::activate_storage($cfg, $target_storeid);
- die "$target_path already exists" if (-e $target_path);
-
- my @created_files = ();
-
- eval {
- if ($vtype eq 'backup') {
- my $target_dirname = dirname($target_path);
- my $info = PVE::Storage::archive_info($source_path);
-
- for my $type (qw(log notes)) {
- my $filename = $info->{"${type}filename"} or next;
- my $auxiliary_source_path = "$source_dirname/$filename";
- my $auxiliary_target_path = "$target_dirname/$filename";
- if (-e $auxiliary_source_path) {
- copy($auxiliary_source_path, $auxiliary_target_path)
- or die "copying backup $type file failed: $!";
- push(@created_files, $auxiliary_target_path);
+
+ if ($vtype eq 'backup' && $target_scfg->{type} eq 'pbs') {
+ PVE::Storage::PBSPlugin::vma_to_pbs(
+ $source_scfg, $source_volid, $target_scfg, $target_storeid);
+ } else {
+ die "expected storage '$target_storeid' to be path based\n" if !$target_scfg->{path};
+ my $target_path = $target_plugin->path($target_scfg, $source_volname, $target_storeid);
+ die "$target_path already exists" if (-e $target_path);
+
+ my @created_files = ();
+
+ eval {
+ if ($vtype eq 'backup') {
+ my $target_dirname = dirname($target_path);
+ my $info = PVE::Storage::archive_info($source_path);
+
+ for my $type (qw(log notes)) {
+ my $filename = $info->{"${type}filename"} or next;
+ my $auxiliary_source_path = "$source_dirname/$filename";
+ my $auxiliary_target_path = "$target_dirname/$filename";
+ if (-e $auxiliary_source_path) {
+ copy($auxiliary_source_path, $auxiliary_target_path)
+ or die "copying backup $type file failed: $!";
+ push(@created_files, $auxiliary_target_path);
+ }
}
- }
- my $protected = $source_plugin->get_volume_attribute(
- $source_scfg, $source_storeid, $source_volname, 'protected');
+ my $protected = $source_plugin->get_volume_attribute(
+ $source_scfg, $source_storeid, $source_volname, 'protected');
- if ($protected) {
- my $protection_target_path = PVE::Storage::protection_file_path($target_path);
- $target_plugin->update_volume_attribute(
- $target_scfg, $target_storeid, $source_volname, 'protected', 1);
- push(@created_files, $protection_target_path);
+ if ($protected) {
+ my $protection_target_path = PVE::Storage::protection_file_path($target_path);
+ $target_plugin->update_volume_attribute(
+ $target_scfg, $target_storeid, $source_volname, 'protected', 1);
+ push(@created_files, $protection_target_path);
+ }
}
- }
- if ($delete) {
- move($source_path, $target_path) or die "failed to move $vtype: $!";
- } else {
- copy($source_path, $target_path) or die "failed to copy $vtype: $!";
- }
- };
- if (my $err = $@) {
- for my $created_file (@created_files) {
- unlink $created_file or $!{ENOENT} or warn $!;
+ if ($delete) {
+ move($source_path, $target_path) or die "failed to move $vtype: $!";
+ } else {
+ copy($source_path, $target_path) or die "failed to copy $vtype: $!";
+ }
+ };
+ if (my $err = $@) {
+ for my $created_file (@created_files) {
+ unlink $created_file or $!{ENOENT} or warn $!;
+ }
+ die $err;
}
- die $err;
}
PVE::Storage::archive_remove($source_path) if $delete;
diff --git a/src/PVE/Storage/PBSPlugin.pm b/src/PVE/Storage/PBSPlugin.pm
index 0808bcc..4f8a05d 100644
--- a/src/PVE/Storage/PBSPlugin.pm
+++ b/src/PVE/Storage/PBSPlugin.pm
@@ -6,6 +6,7 @@ use strict;
use warnings;
use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC);
+use File::Basename;
use IO::File;
use JSON;
use MIME::Base64 qw(decode_base64);
@@ -971,4 +972,68 @@ sub volume_has_feature {
return undef;
}
+sub vma_to_pbs {
+ my ($source_scfg, $source_volid, $target_scfg, $target_storeid) = @_;
+
+ my $source_plugin = PVE::Storage::Plugin->lookup($source_scfg->{type});
+ my $target_plugin = PVE::Storage::Plugin->lookup($target_scfg->{type});
+ my ($source_storeid, $source_volname) = PVE::Storage::parse_volume_id($source_volid, 0);
+ my $source_path = $source_plugin->path($source_scfg, $source_volname, $source_storeid);
+ my $info = PVE::Storage::archive_info($source_path);
+ die "moving non-VMA backups to a Proxmox Backup Server is not supported\n"
+ if $info->{format} ne 'vma';
+
+ my $repo = PVE::PBSClient::get_repository($target_scfg);
+ my $vmid = ($source_plugin->parse_volname($source_volname))[2];
+ my $fingerprint = $target_scfg->{fingerprint};
+ my $password = PVE::Storage::PBSPlugin::pbs_password_file_name($target_scfg, $target_storeid);
+ my $namespace = $target_scfg->{namespace};
+ my $keyfile = PVE::Storage::PBSPlugin::pbs_encryption_key_file_name(
+ $target_scfg, $target_storeid);
+ my $master_keyfile = PVE::Storage::PBSPlugin::pbs_master_pubkey_file_name(
+ $target_scfg, $target_storeid);
+
+ my $comp = $info->{compression};
+ my $backup_time = $info->{ctime};
+ my $source_dirname = dirname($source_path);
+ my $log_file_path = "$source_dirname/$info->{logfilename}";
+ my $notes_file_path = "$source_dirname/$info->{notesfilename}";
+
+ my $vma_to_pbs_cmd = [
+ "vma-to-pbs",
+ "--repository", $repo,
+ "--vmid", $vmid,
+ "--fingerprint", $fingerprint,
+ "--password-file", $password,
+ "--backup-time", $backup_time,
+ "--compress",
+ ];
+
+ push @$vma_to_pbs_cmd, "--ns", $namespace if $namespace;
+ push @$vma_to_pbs_cmd, "--log-file", $log_file_path if -e $log_file_path;
+ push @$vma_to_pbs_cmd, "--notes-file", $notes_file_path if -e $notes_file_path;
+ push @$vma_to_pbs_cmd, "--encrypt", "--keyfile", $keyfile if -e $keyfile;
+ push @$vma_to_pbs_cmd, "--master-keyfile", $master_keyfile if -e $master_keyfile;
+
+ if ($comp) {
+ PVE::Storage::decompress_archive_into_pipe($source_path, $vma_to_pbs_cmd);
+ } else {
+ push @$vma_to_pbs_cmd, $source_path;
+ run_command($vma_to_pbs_cmd);
+ }
+
+ my $protected = $source_plugin->get_volume_attribute(
+ $source_scfg, $source_storeid, $source_volname, 'protected');
+
+ if ($protected) {
+ my $target_volid = PVE::Storage::PBSPlugin::print_volid(
+ $target_storeid, 'vm', $vmid, $backup_time);
+ my (undef, $target_volname) = PVE::Storage::parse_volume_id($target_volid, 0);
+ $target_plugin->update_volume_attribute(
+ $target_scfg, $target_storeid, $target_volname, 'protected', 1);
+ }
+
+ return;
+}
+
1;
--
2.39.2
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2024-09-18 14:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-18 14:49 [pve-devel] [PATCH v4 storage 0/6] support moving volumes between storages Filip Schauer
2024-09-18 14:49 ` [pve-devel] [PATCH v4 storage 1/6] plugin: allow volume import of iso, snippets and vztmpl Filip Schauer
2024-09-20 14:26 ` Daniel Kral
2024-09-18 14:49 ` [pve-devel] [PATCH v4 storage 2/6] api: content: implement moving a volume between storages Filip Schauer
2024-09-20 14:27 ` Daniel Kral
2024-11-26 15:25 ` Filip Schauer
2024-10-21 11:53 ` Fiona Ebner
2024-09-18 14:49 ` [pve-devel] [PATCH v4 storage 3/6] api: content: support moving backups between path based storages Filip Schauer
2024-09-20 14:27 ` Daniel Kral
2024-09-18 14:49 ` [pve-devel] [PATCH v4 storage 4/6] storage: introduce decompress_archive_into_pipe helper Filip Schauer
2024-09-20 14:27 ` Daniel Kral
2024-09-18 14:49 ` Filip Schauer [this message]
2024-09-18 14:49 ` [pve-devel] [PATCH v4 storage 6/6] pvesm: add a move-volume command Filip Schauer
2024-09-20 14:28 ` Daniel Kral
2024-09-20 14:25 ` [pve-devel] [PATCH v4 storage 0/6] support moving volumes between storages Daniel Kral
2024-11-26 15:29 ` Filip Schauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240918144953.130780-6-f.schauer@proxmox.com \
--to=f.schauer@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.