From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34746) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X0bXG-0005o3-Cf for qemu-devel@nongnu.org; Fri, 27 Jun 2014 15:10:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X0bXB-0007D9-48 for qemu-devel@nongnu.org; Fri, 27 Jun 2014 15:10:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:5072) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X0bXA-0007BE-QT for qemu-devel@nongnu.org; Fri, 27 Jun 2014 15:10:05 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5RJA4Te000851 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 27 Jun 2014 15:10:04 -0400 From: Kevin Wolf Date: Fri, 27 Jun 2014 21:08:59 +0200 Message-Id: <1403896146-3063-41-git-send-email-kwolf@redhat.com> In-Reply-To: <1403896146-3063-1-git-send-email-kwolf@redhat.com> References: <1403896146-3063-1-git-send-email-kwolf@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 40/47] qemu-iotests: Add TestRepairQuorum to 041 to test drive-mirror node-name mode. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com From: Beno=C3=AEt Canet The to-replace-node-name is designed to allow repairing a broken Quorum f= ile. This patch introduces a new class TestRepairQuorum testing that the featu= re works. Some further work will be done on QEMU to improve the robustness of the t= ests. Signed-off-by: Benoit Canet Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/041 | 196 +++++++++++++++++++++++++++++++++++++++= +++++- tests/qemu-iotests/041.out | 4 +- 2 files changed, 194 insertions(+), 6 deletions(-) diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index ef4f465..0815e19 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -28,6 +28,12 @@ target_backing_img =3D os.path.join(iotests.test_dir, = 'target-backing.img') test_img =3D os.path.join(iotests.test_dir, 'test.img') target_img =3D os.path.join(iotests.test_dir, 'target.img') =20 +quorum_img1 =3D os.path.join(iotests.test_dir, 'quorum1.img') +quorum_img2 =3D os.path.join(iotests.test_dir, 'quorum2.img') +quorum_img3 =3D os.path.join(iotests.test_dir, 'quorum3.img') +quorum_repair_img =3D os.path.join(iotests.test_dir, 'quorum_repair.img'= ) +quorum_snapshot_file =3D os.path.join(iotests.test_dir, 'quorum_snapshot= .img') + class ImageMirroringTestCase(iotests.QMPTestCase): '''Abstract base class for image mirroring test cases''' =20 @@ -42,8 +48,8 @@ class ImageMirroringTestCase(iotests.QMPTestCase): ready =3D True =20 def wait_ready_and_cancel(self, drive=3D'drive0'): - self.wait_ready(drive) - event =3D self.cancel_and_wait() + self.wait_ready(drive=3Ddrive) + event =3D self.cancel_and_wait(drive=3Ddrive) self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED') self.assert_qmp(event, 'data/type', 'mirror') self.assert_qmp(event, 'data/offset', self.image_len) @@ -52,12 +58,12 @@ class ImageMirroringTestCase(iotests.QMPTestCase): def complete_and_wait(self, drive=3D'drive0', wait_ready=3DTrue): '''Complete a block job and wait for it to finish''' if wait_ready: - self.wait_ready() + self.wait_ready(drive=3Ddrive) =20 result =3D self.vm.qmp('block-job-complete', device=3Ddrive) self.assert_qmp(result, 'return', {}) =20 - event =3D self.wait_until_completed() + event =3D self.wait_until_completed(drive=3Ddrive) self.assert_qmp(event, 'data/type', 'mirror') =20 class TestSingleDrive(ImageMirroringTestCase): @@ -723,5 +729,187 @@ class TestUnbackedSource(ImageMirroringTestCase): self.complete_and_wait() self.assert_no_active_block_jobs() =20 +class TestRepairQuorum(ImageMirroringTestCase): + """ This class test quorum file repair using drive-mirror. + It's mostly a fork of TestSingleDrive """ + image_len =3D 1 * 1024 * 1024 # MB + IMAGES =3D [ quorum_img1, quorum_img2, quorum_img3 ] + + def setUp(self): + self.vm =3D iotests.VM() + + # Add each individual quorum images + for i in self.IMAGES: + qemu_img('create', '-f', iotests.imgfmt, i, + str(TestSingleDrive.image_len)) + # Assign a node name to each quorum image in order to manipu= late + # them + opts =3D "node-name=3Dimg%i" % self.IMAGES.index(i) + self.vm =3D self.vm.add_drive(i, opts) + + self.vm.launch() + + #assemble the quorum block device from the individual files + args =3D { "options" : { "driver": "quorum", "id": "quorum0", + "vote-threshold": 2, "children": [ "img0", "img1", "img= 2" ] } } + result =3D self.vm.qmp("blockdev-add", **args) + self.assert_qmp(result, 'return', {}) + + + def tearDown(self): + self.vm.shutdown() + for i in self.IMAGES + [ quorum_repair_img ]: + # Do a try/except because the test may have deleted some ima= ges + try: + os.remove(i) + except OSError: + pass + + def test_complete(self): + self.assert_no_active_block_jobs() + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D"repair0", + replaces=3D"img1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait(drive=3D"quorum0") + result =3D self.vm.qmp('query-named-block-nodes') + self.assert_qmp(result, 'return[0]/file', quorum_repair_img) + # TODO: a better test requiring some QEMU infrastructure will be= added + # to check that this file is really driven by quorum + self.vm.shutdown() + self.assertTrue(iotests.compare_images(quorum_img2, quorum_repai= r_img), + 'target image does not match source after mirror= ing') + + def test_cancel(self): + self.assert_no_active_block_jobs() + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D"repair0", + replaces=3D"img1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'return', {}) + + self.cancel_and_wait(drive=3D"quorum0", force=3DTrue) + # here we check that the last registered quorum file has not bee= n + # swapped out and unref + result =3D self.vm.qmp('query-named-block-nodes') + self.assert_qmp(result, 'return[0]/file', quorum_img3) + self.vm.shutdown() + + def test_cancel_after_ready(self): + self.assert_no_active_block_jobs() + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D"repair0", + replaces=3D"img1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'return', {}) + + self.wait_ready_and_cancel(drive=3D"quorum0") + result =3D self.vm.qmp('query-named-block-nodes') + # here we check that the last registered quorum file has not bee= n + # swapped out and unref + self.assert_qmp(result, 'return[0]/file', quorum_img3) + self.vm.shutdown() + self.assertTrue(iotests.compare_images(quorum_img2, quorum_repai= r_img), + 'target image does not match source after mirror= ing') + + def test_pause(self): + self.assert_no_active_block_jobs() + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D"repair0", + replaces=3D"img1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'return', {}) + + result =3D self.vm.qmp('block-job-pause', device=3D'quorum0') + self.assert_qmp(result, 'return', {}) + + time.sleep(1) + result =3D self.vm.qmp('query-block-jobs') + offset =3D self.dictpath(result, 'return[0]/offset') + + time.sleep(1) + result =3D self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/offset', offset) + + result =3D self.vm.qmp('block-job-resume', device=3D'quorum0') + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait(drive=3D"quorum0") + self.vm.shutdown() + self.assertTrue(iotests.compare_images(quorum_img2, quorum_repai= r_img), + 'target image does not match source after mirror= ing') + + def test_medium_not_found(self): + result =3D self.vm.qmp('drive-mirror', device=3D'ide1-cd0', sync= =3D'full', + node_name=3D'repair0', + replaces=3D'img1', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_image_not_found(self): + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D'repair0', + replaces=3D'img1', + mode=3D'existing', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_device_not_found(self): + result =3D self.vm.qmp('drive-mirror', device=3D'nonexistent', s= ync=3D'full', + node_name=3D'repair0', + replaces=3D'img1', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_wrong_sync_mode(self): + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', + node_name=3D'repair0', + replaces=3D'img1', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_no_node_name(self): + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + replaces=3D'img1', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_unexistant_replaces(self): + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D'repair0', + replaces=3D'img77', + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_after_a_quorum_snapshot(self): + result =3D self.vm.qmp('blockdev-snapshot-sync', node_name=3D'im= g1', + snapshot_file=3Dquorum_snapshot_file, + snapshot_node_name=3D"snap1"); + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D'repair0', + replaces=3D"img1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sync=3D= 'full', + node_name=3D'repair0', + replaces=3D"snap1", + target=3Dquorum_repair_img, format=3Diotest= s.imgfmt) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait(drive=3D"quorum0") + result =3D self.vm.qmp('query-named-block-nodes') + self.assert_qmp(result, 'return[0]/file', quorum_repair_img) + # TODO: a better test requiring some QEMU infrastructure will be= added + # to check that this file is really driven by quorum + self.vm.shutdown() + if __name__ =3D=3D '__main__': iotests.main(supported_fmts=3D['qcow2', 'qed']) diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out index cfa5c0d..42147c0 100644 --- a/tests/qemu-iotests/041.out +++ b/tests/qemu-iotests/041.out @@ -1,5 +1,5 @@ -................................... +.............................................. ---------------------------------------------------------------------- -Ran 35 tests +Ran 46 tests =20 OK --=20 1.8.3.1