From d29d3d1f80b3947fb26e7139645c83de66d146a9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 10 Mar 2020 12:38:26 +0100 Subject: block: Relax restrictions for blockdev-snapshot blockdev-snapshot returned an error if the overlay was already in use, which it defined as having any BlockBackend parent. This is in fact both too strict (some parents can tolerate the change of visible data caused by attaching a backing file) and too loose (some non-BlockBackend parents may not be happy with it). One important use case that is prevented by the too strict check is live storage migration with blockdev-mirror. Here, the target node is usually opened without a backing file so that the active layer is mirrored while its backing chain can be copied in the background. The backing chain should be attached to the mirror target node when finalising the job, just before switching the users of the source node to the new copy (at which point the mirror job still has a reference to the node). drive-mirror did this automatically, but with blockdev-mirror this is the job of the QMP client, so it needs a way to do this. blockdev-snapshot is the obvious way, so this patch makes it work in this scenario. The new condition is that no parent uses CONSISTENT_READ permissions. This will ensure that the operation will still be blocked when the node is attached to the guest device, so blockdev-snapshot remains safe. (For the sake of completeness, x-blockdev-reopen can be used to achieve the same, however it is a big hammer, performs the graph change completely unchecked and is still experimental. So even with the option of using x-blockdev-reopen, there are reasons why blockdev-snapshot should be able to perform this operation.) Signed-off-by: Kevin Wolf Message-Id: <20200310113831.27293-3-kwolf@redhat.com> Reviewed-by: Peter Krempa Tested-by: Peter Krempa Signed-off-by: Kevin Wolf --- tests/qemu-iotests/085.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out index d94ad22..fd11aae 100644 --- a/tests/qemu-iotests/085.out +++ b/tests/qemu-iotests/085.out @@ -82,7 +82,7 @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f === Invalid command - cannot create a snapshot using a file BDS === { 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } } -{"error": {"class": "GenericError", "desc": "The overlay does not support backing images"}} +{"error": {"class": "GenericError", "desc": "The overlay is already in use"}} === Invalid command - snapshot node used as active layer === @@ -96,7 +96,7 @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f === Invalid command - snapshot node used as backing hd === { 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } } -{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'snap_12'"}} +{"error": {"class": "GenericError", "desc": "The overlay is already in use"}} === Invalid command - snapshot node has a backing image === -- cgit v1.1 From b31b532122ec6f68d17168449c034d2197bf96ec Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 10 Mar 2020 12:38:27 +0100 Subject: iotests: Fix run_job() with use_log=False The 'job-complete' QMP command should be run with qmp() rather than qmp_log() if use_log=False is passed. Signed-off-by: Kevin Wolf Message-Id: <20200310113831.27293-4-kwolf@redhat.com> Reviewed-by: Peter Krempa Signed-off-by: Kevin Wolf --- tests/qemu-iotests/iotests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 8815052..23043ba 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -624,7 +624,10 @@ class VM(qtest.QEMUQtestMachine): if use_log: log('Job failed: %s' % (j['error'])) elif status == 'ready': - self.qmp_log('job-complete', id=job) + if use_log: + self.qmp_log('job-complete', id=job) + else: + self.qmp('job-complete', id=job) elif status == 'pending' and not auto_finalize: if pre_finalize: pre_finalize() -- cgit v1.1 From 8bdee9f10eac2aefdcc5095feef756354c87bdec Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 10 Mar 2020 12:38:28 +0100 Subject: iotests: Test mirror with temporarily disabled target backing file The newly tested scenario is a common live storage migration scenario: The target node is opened without a backing file so that the active layer is mirrored while its backing chain can be copied in the background. The backing chain should be attached to the mirror target node when finalising the job, just before switching the users of the source node to the new copy (at which point the mirror job still has a reference to the node). drive-mirror did this automatically, but with blockdev-mirror this is the job of the QMP client. This patch adds test cases for two ways to achieve the desired result, using either x-blockdev-reopen or blockdev-snapshot. Signed-off-by: Kevin Wolf Message-Id: <20200310113831.27293-5-kwolf@redhat.com> Reviewed-by: Peter Krempa Signed-off-by: Kevin Wolf --- tests/qemu-iotests/155 | 56 +++++++++++++++++++++++++++++++++++++++++----- tests/qemu-iotests/155.out | 4 ++-- 2 files changed, 53 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 index f237868..74ddefc 100755 --- a/tests/qemu-iotests/155 +++ b/tests/qemu-iotests/155 @@ -45,10 +45,15 @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt) # image during runtime, only makes sense if # target_blockdev_backing is not None # (None: same as target_backing) +# target_open_with_backing: If True, the target image is added with its backing +# chain opened right away. If False, blockdev-add +# opens it without a backing file and job completion +# is supposed to open the backing chain. class BaseClass(iotests.QMPTestCase): target_blockdev_backing = None target_real_backing = None + target_open_with_backing = True def setUp(self): qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K') @@ -80,9 +85,13 @@ class BaseClass(iotests.QMPTestCase): options = { 'node-name': 'target', 'driver': iotests.imgfmt, 'file': { 'driver': 'file', + 'node-name': 'target-file', 'filename': target_img } } - if self.target_blockdev_backing: - options['backing'] = self.target_blockdev_backing + + if not self.target_open_with_backing: + options['backing'] = None + elif self.target_blockdev_backing: + options['backing'] = self.target_blockdev_backing result = self.vm.qmp('blockdev-add', **options) self.assert_qmp(result, 'return', {}) @@ -147,10 +156,14 @@ class BaseClass(iotests.QMPTestCase): # cmd: Mirroring command to execute, either drive-mirror or blockdev-mirror class MirrorBaseClass(BaseClass): + def openBacking(self): + pass + def runMirror(self, sync): if self.cmd == 'blockdev-mirror': result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source', - sync=sync, target='target') + sync=sync, target='target', + auto_finalize=False) else: if self.existing: mode = 'existing' @@ -159,11 +172,12 @@ class MirrorBaseClass(BaseClass): result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source', sync=sync, target=target_img, format=iotests.imgfmt, mode=mode, - node_name='target') + node_name='target', auto_finalize=False) self.assert_qmp(result, 'return', {}) - self.complete_and_wait('mirror-job') + self.vm.run_job('mirror-job', use_log=False, auto_finalize=False, + pre_finalize=self.openBacking, auto_dismiss=True) def testFull(self): self.runMirror('full') @@ -221,6 +235,38 @@ class TestBlockdevMirrorForcedBacking(MirrorBaseClass): target_blockdev_backing = { 'driver': 'null-co' } target_real_backing = 'null-co://' +# Attach the backing chain only during completion, with blockdev-reopen +class TestBlockdevMirrorReopen(MirrorBaseClass): + cmd = 'blockdev-mirror' + existing = True + target_backing = 'null-co://' + target_open_with_backing = False + + def openBacking(self): + if not self.target_open_with_backing: + result = self.vm.qmp('blockdev-add', node_name="backing", + driver="null-co") + self.assert_qmp(result, 'return', {}) + result = self.vm.qmp('x-blockdev-reopen', node_name="target", + driver=iotests.imgfmt, file="target-file", + backing="backing") + self.assert_qmp(result, 'return', {}) + +# Attach the backing chain only during completion, with blockdev-snapshot +class TestBlockdevMirrorSnapshot(MirrorBaseClass): + cmd = 'blockdev-mirror' + existing = True + target_backing = 'null-co://' + target_open_with_backing = False + + def openBacking(self): + if not self.target_open_with_backing: + result = self.vm.qmp('blockdev-add', node_name="backing", + driver="null-co") + self.assert_qmp(result, 'return', {}) + result = self.vm.qmp('blockdev-snapshot', node="backing", + overlay="target") + self.assert_qmp(result, 'return', {}) class TestCommit(BaseClass): existing = False diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out index 4176bb9..4fd1c2d 100644 --- a/tests/qemu-iotests/155.out +++ b/tests/qemu-iotests/155.out @@ -1,5 +1,5 @@ -................... +......................... ---------------------------------------------------------------------- -Ran 19 tests +Ran 25 tests OK -- cgit v1.1 From 6a5f6403a11307794ec79d277a065c137cfc12b2 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 10 Mar 2020 12:38:30 +0100 Subject: iotests: Add iothread cases to 155 This patch adds test cases for attaching the backing chain to a mirror job target right before finalising the job, where the image is in a non-mainloop AioContext (i.e. the backing chain needs to be moved to the AioContext of the mirror target). This requires switching the test case from virtio-blk to virtio-scsi because virtio-blk only actually starts using the iothreads when the guest driver initialises the device (which never happens in a test case without a guest OS). virtio-scsi always keeps its block nodes in the AioContext of the the requested iothread without guest interaction. Signed-off-by: Kevin Wolf Message-Id: <20200310113831.27293-7-kwolf@redhat.com> Reviewed-by: Peter Krempa Signed-off-by: Kevin Wolf --- tests/qemu-iotests/155 | 32 +++++++++++++++++++++++--------- tests/qemu-iotests/155.out | 4 ++-- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 index 74ddefc..571bce9 100755 --- a/tests/qemu-iotests/155 +++ b/tests/qemu-iotests/155 @@ -49,11 +49,14 @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt) # chain opened right away. If False, blockdev-add # opens it without a backing file and job completion # is supposed to open the backing chain. +# use_iothread: If True, an iothread is configured for the virtio-blk device +# that uses the image being mirrored class BaseClass(iotests.QMPTestCase): target_blockdev_backing = None target_real_backing = None target_open_with_backing = True + use_iothread = False def setUp(self): qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K') @@ -69,7 +72,16 @@ class BaseClass(iotests.QMPTestCase): 'file': {'driver': 'file', 'filename': source_img}} self.vm.add_blockdev(self.vm.qmp_to_opts(blockdev)) - self.vm.add_device('virtio-blk,id=qdev0,drive=source') + + if self.use_iothread: + self.vm.add_object('iothread,id=iothread0') + iothread = ",iothread=iothread0" + else: + iothread = "" + + self.vm.add_device('virtio-scsi%s' % iothread) + self.vm.add_device('scsi-hd,id=qdev0,drive=source') + self.vm.launch() self.assertIntactSourceBackingChain() @@ -182,24 +194,21 @@ class MirrorBaseClass(BaseClass): def testFull(self): self.runMirror('full') - node = self.findBlockNode('target', - '/machine/peripheral/qdev0/virtio-backend') + node = self.findBlockNode('target', 'qdev0') self.assertCorrectBackingImage(node, None) self.assertIntactSourceBackingChain() def testTop(self): self.runMirror('top') - node = self.findBlockNode('target', - '/machine/peripheral/qdev0/virtio-backend') + node = self.findBlockNode('target', 'qdev0') self.assertCorrectBackingImage(node, back2_img) self.assertIntactSourceBackingChain() def testNone(self): self.runMirror('none') - node = self.findBlockNode('target', - '/machine/peripheral/qdev0/virtio-backend') + node = self.findBlockNode('target', 'qdev0') self.assertCorrectBackingImage(node, source_img) self.assertIntactSourceBackingChain() @@ -252,6 +261,9 @@ class TestBlockdevMirrorReopen(MirrorBaseClass): backing="backing") self.assert_qmp(result, 'return', {}) +class TestBlockdevMirrorReopenIothread(TestBlockdevMirrorReopen): + use_iothread = True + # Attach the backing chain only during completion, with blockdev-snapshot class TestBlockdevMirrorSnapshot(MirrorBaseClass): cmd = 'blockdev-mirror' @@ -268,6 +280,9 @@ class TestBlockdevMirrorSnapshot(MirrorBaseClass): overlay="target") self.assert_qmp(result, 'return', {}) +class TestBlockdevMirrorSnapshotIothread(TestBlockdevMirrorSnapshot): + use_iothread = True + class TestCommit(BaseClass): existing = False @@ -283,8 +298,7 @@ class TestCommit(BaseClass): self.vm.event_wait('BLOCK_JOB_COMPLETED') - node = self.findBlockNode(None, - '/machine/peripheral/qdev0/virtio-backend') + node = self.findBlockNode(None, 'qdev0') self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename', back1_img) self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename', diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out index 4fd1c2d..ed714d5 100644 --- a/tests/qemu-iotests/155.out +++ b/tests/qemu-iotests/155.out @@ -1,5 +1,5 @@ -......................... +............................... ---------------------------------------------------------------------- -Ran 25 tests +Ran 31 tests OK -- cgit v1.1 From 6e1da96b946a1a38d3517564af4e2f572c3ccf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 6 Mar 2020 17:57:51 +0100 Subject: tests/qemu-iotests: Fix socket_scm_helper build path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The socket_scm_helper path got corrupted during the mechanical refactor moving the qtests files into their own sub-directory. Fixes: 1e8a1fae7 ("test: Move qtests to a separate directory") Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200306165751.18986-1-philmd@redhat.com> Reviewed-by: Laurent Vivier Signed-off-by: Kevin Wolf --- tests/Makefile.include | 1 + tests/qtest/Makefile.include | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/Makefile.include b/tests/Makefile.include index edcbd47..67e8fcd 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -589,6 +589,7 @@ include $(SRC_PATH)/tests/qtest/Makefile.include tests/test-qga$(EXESUF): qemu-ga$(EXESUF) tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y) tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a +tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o SPEED = quick diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index 383b0ab..7667299 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -287,7 +287,6 @@ tests/qtest/usb-hcd-ehci-test$(EXESUF): tests/qtest/usb-hcd-ehci-test.o $(libqos tests/qtest/usb-hcd-xhci-test$(EXESUF): tests/qtest/usb-hcd-xhci-test.o $(libqos-usb-obj-y) tests/qtest/cpu-plug-test$(EXESUF): tests/qtest/cpu-plug-test.o tests/qtest/migration-test$(EXESUF): tests/qtest/migration-test.o tests/qtest/migration-helpers.o -tests/qtest/qemu-iotests/qtest/socket_scm_helper$(EXESUF): tests/qtest/qemu-iotests/qtest/socket_scm_helper.o tests/qtest/test-netfilter$(EXESUF): tests/qtest/test-netfilter.o $(qtest-obj-y) tests/qtest/test-filter-mirror$(EXESUF): tests/qtest/test-filter-mirror.o $(qtest-obj-y) tests/qtest/test-filter-redirector$(EXESUF): tests/qtest/test-filter-redirector.o $(qtest-obj-y) -- cgit v1.1 From 8bb3b023f2055054ee119cb45b42d2b14be7fc8a Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 30 Jan 2020 18:39:07 -0300 Subject: qemu-iotests: adding LUKS cleanup for non-UTF8 secret error This patch adds a new test file to exercise the case where qemu-img fails to complete for the LUKS format when a non-UTF8 secret is used. Signed-off-by: Daniel Henrique Barboza Message-Id: <20200130213907.2830642-5-danielhb413@gmail.com> Signed-off-by: Kevin Wolf --- tests/qemu-iotests/282 | 67 ++++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/282.out | 11 ++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 79 insertions(+) create mode 100755 tests/qemu-iotests/282 create mode 100644 tests/qemu-iotests/282.out (limited to 'tests') diff --git a/tests/qemu-iotests/282 b/tests/qemu-iotests/282 new file mode 100755 index 0000000..081eb12 --- /dev/null +++ b/tests/qemu-iotests/282 @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Test qemu-img file cleanup for LUKS when using a non-UTF8 secret +# +# Copyright (C) 2020, IBM Corporation. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! +TEST_IMAGE_FILE='vol.img' + +_cleanup() +{ + _cleanup_test_img + rm non_utf8_secret + rm -f $TEST_IMAGE_FILE +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt luks +_supported_proto generic +_unsupported_proto vxhs + +echo "== Create non-UTF8 secret ==" +echo -n -e '\x3a\x3c\x3b\xff' > non_utf8_secret +SECRET="secret,id=sec0,file=non_utf8_secret" + +echo "== Throws an error because of invalid UTF-8 secret ==" +$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M + +echo "== Image file should not exist after the error ==" +if test -f "$TEST_IMAGE_FILE"; then + exit 1 +fi + +echo "== Create a stub image file and run qemu-img again ==" +touch $TEST_IMAGE_FILE +$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M + +echo "== Pre-existing image file should also be deleted after the error ==" +if test -f "$TEST_IMAGE_FILE"; then + exit 1 +fi + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/282.out b/tests/qemu-iotests/282.out new file mode 100644 index 0000000..5d079da --- /dev/null +++ b/tests/qemu-iotests/282.out @@ -0,0 +1,11 @@ +QA output created by 282 +== Create non-UTF8 secret == +== Throws an error because of invalid UTF-8 secret == +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 +Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 +== Image file should not exist after the error == +== Create a stub image file and run qemu-img again == +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 +Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 +== Pre-existing image file should also be deleted after the error == + *** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 0317667..3c1329b 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -290,6 +290,7 @@ 279 rw backing quick 280 rw migration quick 281 rw quick +282 rw img quick 283 auto quick 284 rw 286 rw quick -- cgit v1.1