[pve-devel] [RFC qemu-server 6/6] restore: allow overriding settings upon restore
Fabian Ebner
f.ebner at proxmox.com
Fri Apr 15 14:31:30 CEST 2022
Specifying a drive parameter causes the restore operation to skip it
and keep the current drive instead.
TODO add some limits to what can be changed?
Signed-off-by: Fabian Ebner <f.ebner at proxmox.com>
---
PVE/API2/Qemu.pm | 14 +++++++++++---
PVE/QemuServer.pm | 44 ++++++++++++++++++++++++++++++++++++++++----
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 976d1bd6..08b1a635 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -823,9 +823,6 @@ __PACKAGE__->register_method({
}
if ($archive) {
- my $keystr = join(' ', keys %$param);
- raise_param_exc({ archive => "option conflicts with other options ($keystr)"}) if $keystr;
-
if ($archive eq '-') {
die "pipe requires cli environment\n" if $rpcenv->{type} ne 'cli';
$archive = { type => 'pipe' };
@@ -873,6 +870,16 @@ __PACKAGE__->register_method({
die "$emsg vm is running\n" if PVE::QemuServer::check_running($vmid);
+ for my $opt (sort keys $param->%*) {
+ next if !PVE::QemuServer::Drive::is_valid_drivename($opt);
+ my $drive = PVE::QemuServer::Drive::parse_drive($opt, $conf->{$opt});
+ my $newdrive = PVE::QemuServer::Drive::parse_drive($opt, $param->{$opt});
+ die "$opt - adding new drive during restore is not implemented\n" if !$drive;
+ die "$opt - unable to parse\n" if !$newdrive;
+ die "$opt - need to pass same volid to keep existing drive rather than restoring\n"
+ if $drive->{file} ne $newdrive->{file};
+ }
+
my $realcmd = sub {
my $restore_options = {
storage => $storage,
@@ -880,6 +887,7 @@ __PACKAGE__->register_method({
unique => $unique,
bwlimit => $bwlimit,
live => $live_restore,
+ override_conf => $param,
};
if ($archive->{type} eq 'file' || $archive->{type} eq 'pipe') {
die "live-restore is only compatible with backup images from a Proxmox Backup Server\n"
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 741a5e89..95ca0444 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -6295,6 +6295,7 @@ my $parse_backup_hints = sub {
while (defined(my $line = <$fh>)) {
if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
+
die "archive does not contain data for drive '$virtdev'\n"
if !$devinfo->{$devname};
@@ -6309,6 +6310,8 @@ my $parse_backup_hints = sub {
$devinfo->{$devname}->{format} = $format;
$devinfo->{$devname}->{storeid} = $storeid;
+ next if $options->{override_conf}->{$virtdev}; # not being restored
+
my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
$check_storage->($storeid, $scfg); # permission and content type check
@@ -6476,6 +6479,17 @@ my $restore_destroy_volumes = sub {
}
};
+my $restore_merge_config = sub {
+ my ($filename, $backup_conf_raw, $override_conf) = @_;
+
+ my $backup_conf = parse_vm_config($filename, $backup_conf_raw);
+ for my $key (keys $override_conf->%*) {
+ $backup_conf->{$key} = $override_conf->{$key};
+ }
+
+ return $backup_conf;
+};
+
sub scan_volids {
my ($cfg, $vmid) = @_;
@@ -6785,8 +6799,10 @@ sub restore_proxmox_backup_archive {
$new_conf_raw .= "\nlock: create";
}
- PVE::Tools::file_set_contents($conffile, $new_conf_raw);
+ my $new_conf = $restore_merge_config->($conffile, $new_conf_raw, $options->{override_conf});
+ PVE::QemuConfig->write_config($vmid, $new_conf);
+ # TODO still needed with write_config?
PVE::Cluster::cfs_update(); # make sure we read new file
eval { rescan($vmid, 1); };
@@ -6808,6 +6824,12 @@ sub restore_proxmox_backup_archive {
# these special drives are already restored before start
delete $devinfo->{'drive-efidisk0'};
delete $devinfo->{'drive-tpmstate0-backup'};
+
+ for my $key (keys $options->{override_conf}->%*) {
+ next if !is_valid_drivename($key);
+ delete $devinfo->{"drive-$key"};
+ }
+
pbs_live_restore($vmid, $conf, $storecfg, $devinfo, $repo, $keyfile, $pbs_backup_name);
PVE::QemuConfig->remove_lock($vmid, "create");
@@ -7000,8 +7022,15 @@ sub restore_vma_archive {
my $map = $restore_allocate_devices->($cfg, $virtdev_hash, $vmid);
# print restore information to $fifofh
- foreach my $virtdev (sort keys %$virtdev_hash) {
- my $d = $virtdev_hash->{$virtdev};
+ for my $devname (sort keys $devinfo->%*) {
+ my $d = $devinfo->{$devname};
+
+ if (!$virtdev_hash->{$d->{virtdev}}) { # skipped
+ print $fifofh "format=raw:0:$d->{devname}=/dev/null\n";
+ print "not restoring '$d->{devname}'\n";
+ next;
+ }
+
next if $d->{is_cloudinit}; # no need to restore cloudinit
my $storeid = $d->{storeid};
@@ -7091,8 +7120,10 @@ sub restore_vma_archive {
die $err;
}
- PVE::Tools::file_set_contents($conffile, $new_conf_raw);
+ my $new_conf = $restore_merge_config->($conffile, $new_conf_raw, $opts->{override_conf});
+ PVE::QemuConfig->write_config($vmid, $new_conf);
+ # TODO still needed with write_config?
PVE::Cluster::cfs_update(); # make sure we read new file
eval { rescan($vmid, 1); };
@@ -7104,6 +7135,11 @@ sub restore_vma_archive {
sub restore_tar_archive {
my ($archive, $vmid, $user, $opts) = @_;
+ if (scalar(keys $opts->{override_conf}->%*) > 0) {
+ my $keystring = join(' ', keys $opts->{override_conf}->%*);
+ die "cannot pass along options ($keystring) when restoring from tar archive\n";
+ }
+
if ($archive ne '-') {
my $firstfile = tar_archive_read_firstfile($archive);
die "ERROR: file '$archive' does not look like a QemuServer vzdump backup\n"
--
2.30.2
More information about the pve-devel
mailing list