Replace the HMP-based test infrastructure with QMP using common.qemu. The old _qemu() function piped HMP commands (savevm, loadvm, delvm, qemu-io) through a monitor stdio pipe. Replace it with interactive QMP control via _launch_qemu / _send_qemu_cmd, using the job-based QMP commands snapshot-save, snapshot-load, and snapshot-delete.
These snapshot commands use the JOB_MANUAL_DISMISS flag, so jobs remain in the "concluded" state until explicitly dismissed. The test handles this through two helpers: - _do_snapshot_cmd(): captures noisy QMP events (JOB_STATUS_CHANGE, STOP, RESUME) during the snapshot operation, silently waits for the job to reach "concluded", then dismisses it with job-dismiss. - _do_snapshot_error(): same flow, but before dismissing, queries the concluded job with query-jobs to retrieve the error message. This preserves the error verification that HMP provided natively through its text output. I/O operations use x-qemu-io via _do_qemu_io(). CLI error cases (e.g. conflicting -loadvm with -incoming defer or -preconfig) invoke QEMU directly with stderr redirected, since those errors are emitted before QMP is available. Signed-off-by: Marc-André Lureau <[email protected]> --- tests/qemu-iotests/tests/qcow2-internal-snapshots | 226 +++++++++++++++------ .../tests/qcow2-internal-snapshots.out | 175 ++++++++++------ 2 files changed, 284 insertions(+), 117 deletions(-) diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots b/tests/qemu-iotests/tests/qcow2-internal-snapshots index d301f0941b5c..3d6da93e6931 100755 --- a/tests/qemu-iotests/tests/qcow2-internal-snapshots +++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots @@ -29,13 +29,16 @@ status=1 # failure is the default! _cleanup() { + _cleanup_qemu _cleanup_test_img } trap "_cleanup; exit \$status" 0 1 2 3 15 # get standard environment, filters and checks -. ../common.rc -. ../common.filter +cd .. +. ./common.rc +. ./common.filter +. ./common.qemu # This tests qcow2-specific low-level functionality _supported_fmt qcow2 @@ -43,20 +46,78 @@ _supported_proto file # Internal snapshots are (currently) impossible with refcount_bits=1, # and generally impossible with external data files _unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file -_require_hmp IMG_SIZE=64M -_qemu() +QEMU_ARGS="-no-shutdown -nodefaults \ + -blockdev file,filename=$TEST_IMG,node-name=disk0-file \ + -blockdev $IMGFMT,file=disk0-file,node-name=disk0 \ + -object iothread,id=iothread0 \ + -device virtio-scsi,iothread=iothread0 \ + -device scsi-hd,drive=disk0,share-rw=on" + +_do_qemu_io() { - $QEMU -no-shutdown -nographic -monitor stdio -serial none \ - -blockdev file,filename="$TEST_IMG",node-name=disk0-file \ - -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \ - -object iothread,id=iothread0 \ - -device virtio-scsi,iothread=iothread0 \ - -device scsi-hd,drive=disk0,share-rw=on \ - "$@" 2>&1 |\ - _filter_qemu | _filter_hmp | _filter_qemu_io + _send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': '$1' } }" \ + 'return' +} + +_do_snapshot_cmd() +{ + local cmd="$1" job_id="$2" + capture_events="JOB_STATUS_CHANGE STOP RESUME" \ + _send_qemu_cmd $QEMU_HANDLE "$cmd" 'return' + silent=yes _send_qemu_cmd $QEMU_HANDLE '' '"concluded"' + silent=yes capture_events="JOB_STATUS_CHANGE" \ + _send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'job-dismiss', + 'arguments': { 'id': '$job_id' } }" \ + 'return' +} + +_do_snapshot_save() +{ + _do_snapshot_cmd \ + "{ 'execute': 'snapshot-save', + 'arguments': { 'job-id': '$2', 'tag': '$1', + 'vmstate': 'disk0', + 'devices': [\"disk0\"] } }" "$2" +} + +_do_snapshot_load() +{ + _do_snapshot_cmd \ + "{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': '$2', 'tag': '$1', + 'vmstate': 'disk0', + 'devices': [\"disk0\"] } }" "$2" +} + +_do_snapshot_delete() +{ + _do_snapshot_cmd \ + "{ 'execute': 'snapshot-delete', + 'arguments': { 'job-id': '$2', 'tag': '$1', + 'devices': [\"disk0\"] } }" "$2" +} + +_do_snapshot_error() +{ + local cmd="$1" job_id="$2" + capture_events="JOB_STATUS_CHANGE STOP RESUME" \ + _send_qemu_cmd $QEMU_HANDLE "$cmd" 'return' + silent=yes _send_qemu_cmd $QEMU_HANDLE '' '"concluded"' + _send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'query-jobs' }" \ + 'return' + silent=yes capture_events="JOB_STATUS_CHANGE" \ + _send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'job-dismiss', + 'arguments': { 'id': '$job_id' } }" \ + 'return' } _make_test_img $IMG_SIZE @@ -65,14 +126,16 @@ echo echo "=== Write some data, take a snapshot and overwrite part of it ===" echo -{ - echo 'qemu-io disk0 "write -P0x11 0 1M"' - # Give qemu some time to boot before saving the VM state - sleep 0.5 - echo "savevm snap0" - echo 'qemu-io disk0 "write -P0x22 0 512k"' - echo "quit" -} | _qemu +_launch_qemu $QEMU_ARGS +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" 'return' + +_do_qemu_io "write -P0x11 0 1M" +_do_snapshot_save snap0 save0 +_do_qemu_io "write -P0x22 0 512k" + +capture_events="JOB_STATUS_CHANGE SHUTDOWN" \ +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'quit' }" 'return' +wait=1 _cleanup_qemu echo $QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size @@ -82,26 +145,29 @@ echo echo "=== Verify that loading the snapshot reverts to the old content ===" echo -{ - # -loadvm reverted the write from the previous QEMU instance - echo 'qemu-io disk0 "read -P0x11 0 1M"' +# -loadvm reverts the write from the previous QEMU instance +_launch_qemu $QEMU_ARGS -loadvm snap0 +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" 'return' - # Verify that it works without restarting QEMU, too - echo 'qemu-io disk0 "write -P0x33 512k 512k"' - echo "loadvm snap0" - echo 'qemu-io disk0 "read -P0x11 0 1M"' +_do_qemu_io "read -P0x11 0 1M" - # Verify COW by writing a partial cluster - echo 'qemu-io disk0 "write -P0x33 63k 2k"' - echo 'qemu-io disk0 "read -P0x11 0 63k"' - echo 'qemu-io disk0 "read -P0x33 63k 2k"' - echo 'qemu-io disk0 "read -P0x11 65k 63k"' +# Verify that it works without restarting QEMU, too +_do_qemu_io "write -P0x33 512k 512k" +_do_snapshot_load snap0 load0 +_do_qemu_io "read -P0x11 0 1M" - # Take a second snapshot - echo "savevm snap1" +# Verify COW by writing a partial cluster +_do_qemu_io "write -P0x33 63k 2k" +_do_qemu_io "read -P0x11 0 63k" +_do_qemu_io "read -P0x33 63k 2k" +_do_qemu_io "read -P0x11 65k 63k" - echo "quit" -} | _qemu -loadvm snap0 +# Take a second snapshot +_do_snapshot_save snap1 save1 + +capture_events="JOB_STATUS_CHANGE SHUTDOWN" \ +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'quit' }" 'return' +wait=1 _cleanup_qemu echo $QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size @@ -123,15 +189,19 @@ $QEMU_IO \ echo echo "=== Deleting snapshots ===" echo -{ - # The active layer stays unaffected by deleting the snapshot - echo "delvm snap1" - echo 'qemu-io disk0 "read -P0x11 0 63k"' - echo 'qemu-io disk0 "read -P0x33 63k 2k"' - echo 'qemu-io disk0 "read -P0x11 65k 63k"' - echo "quit" -} | _qemu +_launch_qemu $QEMU_ARGS +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" 'return' + +# The active layer stays unaffected by deleting the snapshot +_do_snapshot_delete snap1 del0 +_do_qemu_io "read -P0x11 0 63k" +_do_qemu_io "read -P0x33 63k 2k" +_do_qemu_io "read -P0x11 65k 63k" + +capture_events="JOB_STATUS_CHANGE SHUTDOWN" \ +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'quit' }" 'return' +wait=1 _cleanup_qemu echo @@ -143,27 +213,69 @@ echo "=== Error cases ===" echo # snap1 should not exist any more -_qemu -loadvm snap1 +$QEMU -no-shutdown -nographic -serial none -nodefaults \ + -blockdev file,filename="$TEST_IMG",node-name=disk0-file \ + -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \ + -object iothread,id=iothread0 \ + -device virtio-scsi,iothread=iothread0 \ + -device scsi-hd,drive=disk0,share-rw=on \ + -loadvm snap1 2>&1 | _filter_qemu echo -{ - echo "loadvm snap1" - echo "quit" -} | _qemu +_launch_qemu $QEMU_ARGS +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" 'return' +_do_snapshot_error \ + "{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': 'load1', 'tag': 'snap1', + 'vmstate': 'disk0', + 'devices': [\"disk0\"] } }" load1 +capture_events="JOB_STATUS_CHANGE SHUTDOWN" \ +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'quit' }" 'return' +wait=1 _cleanup_qemu # Snapshot operations and inactive images are incompatible echo -_qemu -loadvm snap0 -incoming defer -{ - echo "loadvm snap0" - echo "delvm snap0" - echo "savevm snap1" - echo "quit" -} | _qemu -incoming defer +$QEMU -no-shutdown -nographic -serial none -nodefaults \ + -blockdev file,filename="$TEST_IMG",node-name=disk0-file \ + -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \ + -object iothread,id=iothread0 \ + -device virtio-scsi,iothread=iothread0 \ + -device scsi-hd,drive=disk0,share-rw=on \ + -loadvm snap0 -incoming defer 2>&1 | _filter_qemu + +_launch_qemu $QEMU_ARGS -incoming defer +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" 'return' + +_do_snapshot_error \ + "{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': 'load2', 'tag': 'snap0', + 'vmstate': 'disk0', + 'devices': [\"disk0\"] } }" load2 + +_do_snapshot_error \ + "{ 'execute': 'snapshot-delete', + 'arguments': { 'job-id': 'del2', 'tag': 'snap0', + 'devices': [\"disk0\"] } }" del2 + +_do_snapshot_error \ + "{ 'execute': 'snapshot-save', + 'arguments': { 'job-id': 'save2', 'tag': 'snap1', + 'vmstate': 'disk0', + 'devices': [\"disk0\"] } }" save2 + +capture_events="JOB_STATUS_CHANGE SHUTDOWN" \ +_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'quit' }" 'return' +wait=1 _cleanup_qemu # -loadvm and -preconfig are incompatible echo -_qemu -loadvm snap0 -preconfig +$QEMU -no-shutdown -nographic -serial none -nodefaults \ + -blockdev file,filename="$TEST_IMG",node-name=disk0-file \ + -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \ + -object iothread,id=iothread0 \ + -device virtio-scsi,iothread=iothread0 \ + -device scsi-hd,drive=disk0,share-rw=on \ + -loadvm snap0 -preconfig 2>&1 | _filter_qemu # success, all done echo "*** done" diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots.out b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out index fedb09224ea4..fb602505553b 100644 --- a/tests/qemu-iotests/tests/qcow2-internal-snapshots.out +++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out @@ -3,15 +3,23 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 === Write some data, take a snapshot and overwrite part of it === -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) qemu-io disk0 "write -P0x11 0 1M" -wrote 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) savevm snap0 -(qemu) qemu-io disk0 "write -P0x22 0 512k" -wrote 524288/524288 bytes at offset 0 -512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) quit +{ 'execute': 'qmp_capabilities' } +{"return": {}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'write -P0x11 0 1M' } } +{"return": {"human-readable-text": "wrote 1048576/1048576 bytes at offset 0\n1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'snapshot-save', + 'arguments': { 'job-id': 'save0', 'tag': 'snap0', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'write -P0x22 0 512k' } } +{"return": {"human-readable-text": "wrote 524288/524288 bytes at offset 0\n512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'quit' } +{"return": {}} Snapshot list: ID TAG VM_SIZE DATE VM_CLOCK ICOUNT @@ -20,31 +28,48 @@ No errors were found on the image. === Verify that loading the snapshot reverts to the old content === -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) qemu-io disk0 "read -P0x11 0 1M" -read 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "write -P0x33 512k 512k" -wrote 524288/524288 bytes at offset 524288 -512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) loadvm snap0 -(qemu) qemu-io disk0 "read -P0x11 0 1M" -read 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "write -P0x33 63k 2k" -wrote 2048/2048 bytes at offset 64512 -2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "read -P0x11 0 63k" -read 64512/64512 bytes at offset 0 -63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "read -P0x33 63k 2k" -read 2048/2048 bytes at offset 64512 -2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "read -P0x11 65k 63k" -read 64512/64512 bytes at offset 66560 -63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) savevm snap1 -(qemu) quit +{ 'execute': 'qmp_capabilities' } +{"return": {}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 0 1M' } } +{"return": {"human-readable-text": "read 1048576/1048576 bytes at offset 0\n1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'write -P0x33 512k 512k' } } +{"return": {"human-readable-text": "wrote 524288/524288 bytes at offset 524288\n512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': 'load0', 'tag': 'snap0', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 0 1M' } } +{"return": {"human-readable-text": "read 1048576/1048576 bytes at offset 0\n1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'write -P0x33 63k 2k' } } +{"return": {"human-readable-text": "wrote 2048/2048 bytes at offset 64512\n2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 0 63k' } } +{"return": {"human-readable-text": "read 64512/64512 bytes at offset 0\n63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x33 63k 2k' } } +{"return": {"human-readable-text": "read 2048/2048 bytes at offset 64512\n2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 65k 63k' } } +{"return": {"human-readable-text": "read 64512/64512 bytes at offset 66560\n63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'snapshot-save', + 'arguments': { 'job-id': 'save1', 'tag': 'snap1', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'quit' } +{"return": {}} Snapshot list: ID TAG VM_SIZE DATE VM_CLOCK ICOUNT @@ -65,18 +90,26 @@ read 64512/64512 bytes at offset 66560 === Deleting snapshots === -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) delvm snap1 -(qemu) qemu-io disk0 "read -P0x11 0 63k" -read 64512/64512 bytes at offset 0 -63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "read -P0x33 63k 2k" -read 2048/2048 bytes at offset 64512 -2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) qemu-io disk0 "read -P0x11 65k 63k" -read 64512/64512 bytes at offset 66560 -63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) quit +{ 'execute': 'qmp_capabilities' } +{"return": {}} +{ 'execute': 'snapshot-delete', + 'arguments': { 'job-id': 'del0', 'tag': 'snap1', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 0 63k' } } +{"return": {"human-readable-text": "read 64512/64512 bytes at offset 0\n63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x33 63k 2k' } } +{"return": {"human-readable-text": "read 2048/2048 bytes at offset 64512\n2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'x-qemu-io', + 'arguments': { 'device': 'disk0', + 'command': 'read -P0x11 65k 63k' } } +{"return": {"human-readable-text": "read 64512/64512 bytes at offset 66560\n63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)\n"}} +{ 'execute': 'quit' } +{"return": {}} Snapshot list: ID TAG VM_SIZE DATE VM_CLOCK ICOUNT @@ -85,23 +118,45 @@ No errors were found on the image. === Error cases === -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Snapshot 'snap1' does not exist in one or more devices +QEMU_PROG: Snapshot 'snap1' does not exist in one or more devices -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) loadvm snap1 -Error: Snapshot 'snap1' does not exist in one or more devices -(qemu) quit +{ 'execute': 'qmp_capabilities' } +{"return": {}} +{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': 'load1', 'tag': 'snap1', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'query-jobs' } +{"return": [{"current-progress": 1, "status": "concluded", "total-progress": 1, "type": "snapshot-load", "id": "load1", "error": "Snapshot 'snap1' does not exist in one or more devices"}]} +{ 'execute': 'quit' } +{"return": {}} QEMU_PROG: 'incoming' and 'loadvm' options are mutually exclusive -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) loadvm snap0 -Error: Device 'disk0' is writable but does not support snapshots -(qemu) delvm snap0 -Error: Device 'disk0' is writable but does not support snapshots -(qemu) savevm snap1 -Error: Device 'disk0' is writable but does not support snapshots -(qemu) quit +{ 'execute': 'qmp_capabilities' } +{"return": {}} +{ 'execute': 'snapshot-load', + 'arguments': { 'job-id': 'load2', 'tag': 'snap0', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'query-jobs' } +{"return": [{"current-progress": 1, "status": "concluded", "total-progress": 1, "type": "snapshot-load", "id": "load2", "error": "Device 'disk0' is writable but does not support snapshots"}]} +{ 'execute': 'snapshot-delete', + 'arguments': { 'job-id': 'del2', 'tag': 'snap0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'query-jobs' } +{"return": [{"current-progress": 1, "status": "concluded", "total-progress": 1, "type": "snapshot-delete", "id": "del2", "error": "Device 'disk0' is writable but does not support snapshots"}]} +{ 'execute': 'snapshot-save', + 'arguments': { 'job-id': 'save2', 'tag': 'snap1', + 'vmstate': 'disk0', + 'devices': ["disk0"] } } +{"return": {}} +{ 'execute': 'query-jobs' } +{"return": [{"current-progress": 1, "status": "concluded", "total-progress": 1, "type": "snapshot-save", "id": "save2", "error": "Device 'disk0' is writable but does not support snapshots"}]} +{ 'execute': 'quit' } +{"return": {}} QEMU_PROG: 'preconfig' and 'loadvm' options are mutually exclusive *** done -- 2.56.0.rc0.29.g47ce80527c56
