* [PATCH qemu-server] fix #6391: restore: fall back to automatic VM state storage if unavailable
@ 2026-10-16 13:31 Michal Fox
0 siblings, 0 replies; only message in thread
From: Michal Fox @ 2026-10-16 13:31 UTC (permalink / raw)
To: pve-devel
Restoring a backup keeps the 'vmstatestorage' option of the backed up
VM. When the backup is restored on another node or cluster, that
storage might not exist there or not be enabled for the node, so that
hibernating the VM or taking a snapshot including RAM fails later on,
for example with "storage 'local-zfs-pve1' does not exist".
If the configured VM state storage is not available on the node the
backup is restored to, drop the option, so that the storage is
selected automatically, like for VMs without it, and log that in the
restore task log.
A 'vmstatestorage' passed explicitly when restoring is applied after
this and is not affected.
Signed-off-by: Michal Fox <me@dualfroz.com>
---
Tested with new restore config test cases for a VM state storage that
exists, does not exist, is restricted to another node and is disabled.
Without the fix, the last three keep the option. The whole qemu-server
test suite passes.
The message is printed as a plain log line, not as a warning, since
the restore itself is fine. Happy to switch to log_warn() if that is
preferred.
src/PVE/QemuServer.pm | 10 +++++++++
src/test/restore-config-expected/201.conf | 13 ++++++++++++
src/test/restore-config-expected/202.conf | 12 +++++++++++
src/test/restore-config-expected/203.conf | 12 +++++++++++
src/test/restore-config-expected/204.conf | 12 +++++++++++
src/test/restore-config-input/201.conf | 14 +++++++++++++
src/test/restore-config-input/202.conf | 14 +++++++++++++
src/test/restore-config-input/203.conf | 14 +++++++++++++
src/test/restore-config-input/204.conf | 14 +++++++++++++
src/test/run_qemu_restore_config_tests.pl | 25 ++++++++++++++++++++++-
10 files changed, 139 insertions(+), 1 deletion(-)
create mode 100644 src/test/restore-config-expected/201.conf
create mode 100644 src/test/restore-config-expected/202.conf
create mode 100644 src/test/restore-config-expected/203.conf
create mode 100644 src/test/restore-config-expected/204.conf
create mode 100644 src/test/restore-config-input/201.conf
create mode 100644 src/test/restore-config-input/202.conf
create mode 100644 src/test/restore-config-input/203.conf
create mode 100644 src/test/restore-config-input/204.conf
diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index f199371d..62fb72ef 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -6697,6 +6697,16 @@ sub restore_update_config_line {
} else {
$res .= $line;
}
+ } elsif ($line =~ m/^vmstatestorage:\s*(\S+)\s*$/) {
+ my $storeid = $1;
+ my $storecfg = PVE::Storage::config();
+ my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
+ if ($scfg && PVE::Storage::storage_check_enabled($storecfg, $storeid, undef, 1)) {
+ $res .= $line;
+ } else {
+ print "VM state storage '$storeid' is not available on this node, using"
+ . " automatic selection instead\n";
+ }
} elsif (($line =~ m/^vmgenid: (.*)/)) {
my $vmgenid = $1;
if ($vmgenid ne '0') {
diff --git a/src/test/restore-config-expected/201.conf b/src/test/restore-config-expected/201.conf
new file mode 100644
index 00000000..c76a010e
--- /dev/null
+++ b/src/test/restore-config-expected/201.conf
@@ -0,0 +1,13 @@
+# VM state storage available on the target is kept
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: target:201/vm-201-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
+vmstatestorage: mydir
diff --git a/src/test/restore-config-expected/202.conf b/src/test/restore-config-expected/202.conf
new file mode 100644
index 00000000..f46451fe
--- /dev/null
+++ b/src/test/restore-config-expected/202.conf
@@ -0,0 +1,12 @@
+# VM state storage missing on the target falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: target:202/vm-202-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
diff --git a/src/test/restore-config-expected/203.conf b/src/test/restore-config-expected/203.conf
new file mode 100644
index 00000000..6f93f8c0
--- /dev/null
+++ b/src/test/restore-config-expected/203.conf
@@ -0,0 +1,12 @@
+# VM state storage not available on this node falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: target:203/vm-203-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
diff --git a/src/test/restore-config-expected/204.conf b/src/test/restore-config-expected/204.conf
new file mode 100644
index 00000000..926dab25
--- /dev/null
+++ b/src/test/restore-config-expected/204.conf
@@ -0,0 +1,12 @@
+# disabled VM state storage falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: target:204/vm-204-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
diff --git a/src/test/restore-config-input/201.conf b/src/test/restore-config-input/201.conf
new file mode 100644
index 00000000..4459b739
--- /dev/null
+++ b/src/test/restore-config-input/201.conf
@@ -0,0 +1,14 @@
+# VM state storage available on the target is kept
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: mydir:201/vm-201-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
+vmstatestorage: mydir
+#qmdump#map:scsi0:drive-scsi0:mydir:qcow2:
diff --git a/src/test/restore-config-input/202.conf b/src/test/restore-config-input/202.conf
new file mode 100644
index 00000000..15c340d2
--- /dev/null
+++ b/src/test/restore-config-input/202.conf
@@ -0,0 +1,14 @@
+# VM state storage missing on the target falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: mydir:202/vm-202-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
+vmstatestorage: local-zfs-pve1
+#qmdump#map:scsi0:drive-scsi0:mydir:qcow2:
diff --git a/src/test/restore-config-input/203.conf b/src/test/restore-config-input/203.conf
new file mode 100644
index 00000000..8f152775
--- /dev/null
+++ b/src/test/restore-config-input/203.conf
@@ -0,0 +1,14 @@
+# VM state storage not available on this node falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: mydir:203/vm-203-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
+vmstatestorage: othernode
+#qmdump#map:scsi0:drive-scsi0:mydir:qcow2:
diff --git a/src/test/restore-config-input/204.conf b/src/test/restore-config-input/204.conf
new file mode 100644
index 00000000..bb8f5788
--- /dev/null
+++ b/src/test/restore-config-input/204.conf
@@ -0,0 +1,14 @@
+# disabled VM state storage falls back to automatic selection
+boot: order=scsi0
+cores: 1
+memory: 2048
+name: hibernated
+net0: virtio=BC:24:11:6B:2A:5F,bridge=vmbr0
+ostype: win10
+scsi0: mydir:204/vm-204-disk-0.qcow2,size=32G
+scsihw: virtio-scsi-single
+smbios1: uuid=0c5a8b3e-9d43-4bd1-8a0e-3f6f2b1f3c11
+sockets: 1
+vmgenid: 0
+vmstatestorage: disabledstore
+#qmdump#map:scsi0:drive-scsi0:mydir:qcow2:
diff --git a/src/test/run_qemu_restore_config_tests.pl b/src/test/run_qemu_restore_config_tests.pl
index 4d5ebb5f..8982fe90 100755
--- a/src/test/run_qemu_restore_config_tests.pl
+++ b/src/test/run_qemu_restore_config_tests.pl
@@ -17,7 +17,7 @@ my $INPUT_DIR = './restore-config-input';
my $EXPECTED_DIR = './restore-config-expected';
# NOTE update when you add/remove tests
-plan tests => 4;
+plan tests => 8;
my $pve_cluster_module = Test::MockModule->new("PVE::Cluster");
$pve_cluster_module->mock(
@@ -32,6 +32,29 @@ $pve_cluster_module->mock(
},
);
+my $pve_storage_module = Test::MockModule->new("PVE::Storage");
+$pve_storage_module->mock(
+ config => sub {
+ return {
+ ids => {
+ mydir => { type => 'dir', path => '/mnt/mydir', content => { images => 1 } },
+ othernode => {
+ type => 'dir',
+ path => '/mnt/othernode',
+ content => { images => 1 },
+ nodes => { 'some-other-node' => 1 },
+ },
+ disabledstore => {
+ type => 'dir',
+ path => '/mnt/disabled',
+ content => { images => 1 },
+ disable => 1,
+ },
+ },
+ };
+ },
+);
+
dir_glob_foreach(
'./restore-config-input',
'[0-9]+.conf',
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-16 13:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 13:31 [PATCH qemu-server] fix #6391: restore: fall back to automatic VM state storage if unavailable Michal Fox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox