use PVE::IPCC;
use PVE::JSONSchema;
use PVE::PBSClient;
+use PVE::RESTEnvironment qw(log_warn);
use PVE::QMPClient;
use PVE::Storage::Plugin;
use PVE::Storage::PBSPlugin;
}
next if !$path;
- my ($size, $format) = eval { PVE::Storage::volume_size_info($self->{storecfg}, $volid, 5) };
- die "no such volume '$volid'\n" if $@;
+ my ($size, $format);
+ if ($storeid) {
+ # The call in list context can be expensive for certain plugins like RBD, just get size
+ $size = eval { PVE::Storage::volume_size_info($self->{storecfg}, $volid, 5) };
+ die "cannot determine size of volume '$volid' - $@\n" if $@;
+
+ my $scfg = PVE::Storage::storage_config($self->{storecfg}, $storeid);
+ $format = PVE::QemuServer::qemu_img_format($scfg, $volname);
+ } else {
+ ($size, $format) = eval {
+ PVE::Storage::volume_size_info($self->{storecfg}, $volid, 5);
+ };
+ die "cannot determine size and format of volume '$volid' - $@\n" if $@;
+ }
my $diskinfo = {
path => $path,
my $found_snapshot;
my $found_pending;
+ my $found_cloudinit;
while (defined (my $line = <$conffd>)) {
next if $line =~ m/^\#vzdump\#/; # just to be sure
next if $line =~ m/^\#qmdump\#/; # just to be sure
if ($line =~ m/^\[(.*)\]\s*$/) {
if ($1 =~ m/PENDING/i) {
$found_pending = 1;
+ } elsif ($1 =~ m/special:cloudinit/) {
+ $found_cloudinit = 1;
} else {
$found_snapshot = 1;
}
}
- next if $found_snapshot || $found_pending; # skip all snapshots and pending changes config data
+ next if $found_snapshot || $found_pending || $found_cloudinit; # skip all snapshots,pending changes and cloudinit config data
if ($line =~ m/^unused\d+:\s*(\S+)\s*/) {
$self->loginfo("skip unused drive '$1' (not included into backup)");
eval { PVE::QemuServer::qemu_drivedel($vmid, "tpmstate0-backup"); };
};
+my sub add_backup_performance_options {
+ my ($qmp_param, $perf, $qemu_support) = @_;
+
+ return if !$perf || scalar(keys $perf->%*) == 0;
+
+ if (!$qemu_support) {
+ my $settings_string = join(', ', sort keys $perf->%*);
+ log_warn("ignoring setting(s): $settings_string - issue checking if supported");
+ return;
+ }
+
+ if (defined($perf->{'max-workers'})) {
+ if ($qemu_support->{'backup-max-workers'}) {
+ $qmp_param->{'max-workers'} = int($perf->{'max-workers'});
+ } else {
+ log_warn("ignoring 'max-workers' setting - not supported by running QEMU");
+ }
+ }
+}
+
sub archive_pbs {
my ($self, $task, $vmid) = @_;
# proxmox-backup-client can only handle raw files and block devs
# only use it (directly) for disk-less VMs
if (!$diskcount) {
- my @pathlist;
$self->loginfo("backup contains no disks");
local $ENV{PBS_PASSWORD} = $password;
if (defined(my $ns = $scfg->{namespace})) {
push @$cmd, '--ns', $ns;
}
+ if (-e $keyfile) {
+ $self->loginfo("enabling encryption");
+ push @$cmd, '--keyfile', $keyfile;
+ if (defined($master_keyfile)) {
+ if (-e $master_keyfile) {
+ $self->loginfo("enabling master key feature");
+ push @$cmd, '--master-pubkey-file', $master_keyfile;
+ } elsif ($scfg->{'master-pubkey'}) {
+ die "master public key configured but no key file found\n";
+ }
+ }
+ } else {
+ my $encryption_fp = $scfg->{'encryption-key'};
+ die "encryption configured ('$encryption_fp') but no encryption key file found!\n"
+ if $encryption_fp;
+ $self->loginfo("WARNING: backup target is configured with master key, but this backup is not encrypted - master key settings will be ignored!")
+ if defined($master_keyfile) && -e $master_keyfile;
+ }
push @$cmd, "qemu-server.conf:$conffile";
push @$cmd, "fw.conf:$firewall" if -e $firewall;
}
}
- if (!defined($qemu_support->{"pbs-masterkey"}) && -e $master_keyfile) {
- $self->loginfo("WARNING: backup target is configured with master key, but running QEMU version does not support master keys.");
- $self->loginfo("Please make sure you've installed the latest version and the VM has been restarted to use master key feature.");
- $master_keyfile = undef; # skip rest of master key handling below
- }
+ # pve-qemu supports it since 5.2.0-1 (PVE 6.4), so safe to die since PVE 8
+ die "master key configured but running QEMU version does not support master keys\n"
+ if !defined($qemu_support->{'pbs-masterkey'}) && -e $master_keyfile;
$attach_tpmstate_drive->($self, $task, $vmid);
if (defined(my $ns = $scfg->{namespace})) {
$params->{'backup-ns'} = $ns;
}
+
$params->{speed} = $opts->{bwlimit}*1024 if $opts->{bwlimit};
+ add_backup_performance_options($params, $opts->{performance}, $qemu_support);
+
$params->{fingerprint} = $fingerprint if defined($fingerprint);
$params->{'firewall-file'} = $firewall if -e $firewall;
if (-e $keyfile) {
die "interrupted by signal\n";
};
+ # Currently, failing to determine Proxmox support is not critical here, because it's only
+ # used for performance settings like 'max-workers'.
+ my $qemu_support = eval { mon_cmd($vmid, "query-proxmox-support") };
+ log_warn($@) if $@;
+
$attach_tpmstate_drive->($self, $task, $vmid);
my $outfh;
devlist => $devlist
};
$params->{'firewall-file'} = $firewall if -e $firewall;
+ add_backup_performance_options($params, $opts->{performance}, $qemu_support);
$qmpclient->queue_cmd($vmid, $backup_cb, 'backup', %$params);
};
return;
}
+ my $freeze = PVE::QemuServer::get_qga_key($self->{vmlist}->{$vmid}, 'freeze-fs-on-backup') // 1;
+ if (!$freeze) {
+ $self->loginfo("skipping guest-agent 'fs-freeze', disabled in VM options");
+ return;
+ }
+
$self->loginfo("issuing guest-agent 'fs-freeze' command");
eval { mon_cmd($vmid, "guest-fsfreeze-freeze") };
$self->logerr($@) if $@;