]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/VZDump/QemuServer.pm
vzdump: error out for master-key backup but no QEMU support
[qemu-server.git] / PVE / VZDump / QemuServer.pm
index bf0d1c56fbf951bc3fe2a0fcd03e6e96fbf7e801..7bd2a4150704809bc0d1f0f81d9c4413b0a6add8 100644 (file)
@@ -15,6 +15,7 @@ use PVE::INotify;
 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;
@@ -118,8 +119,20 @@ sub prepare {
        }
        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,
@@ -214,17 +227,20 @@ sub assemble {
 
     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)");
@@ -453,6 +469,26 @@ my $detach_tpmstate_drive = sub {
     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) = @_;
 
@@ -474,7 +510,6 @@ sub archive_pbs {
     # 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;
@@ -490,6 +525,24 @@ sub archive_pbs {
        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;
@@ -526,11 +579,9 @@ sub archive_pbs {
            }
        }
 
-       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);
 
@@ -548,7 +599,10 @@ sub archive_pbs {
        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) {
@@ -716,6 +770,11 @@ sub archive_vma {
            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;
@@ -746,6 +805,7 @@ sub archive_vma {
                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);
        };
@@ -829,6 +889,12 @@ sub qga_fs_freeze {
        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 $@;