From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59812) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwTgE-0007QJ-9z for qemu-devel@nongnu.org; Mon, 16 Jun 2014 05:58:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WwTg9-00024Y-4b for qemu-devel@nongnu.org; Mon, 16 Jun 2014 05:58:22 -0400 Received: from lputeaux-656-01-25-125.w80-12.abo.wanadoo.fr ([80.12.84.125]:51367 helo=paradis.irqsave.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwTg8-00024M-Qr for qemu-devel@nongnu.org; Mon, 16 Jun 2014 05:58:17 -0400 Date: Mon, 16 Jun 2014 11:58:14 +0200 From: =?iso-8859-1?Q?Beno=EEt?= Canet Message-ID: <20140616095814.GA10290@irqsave.net> References: <1402493053-13787-1-git-send-email-benoit.canet@irqsave.net> <1402493053-13787-5-git-send-email-benoit.canet@irqsave.net> <539B9AED.9060408@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <539B9AED.9060408@redhat.com> Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v9 4/4] 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: Max Reitz Cc: =?iso-8859-1?Q?Beno=EEt?= Canet , kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com The Saturday 14 Jun 2014 =E0 02:44:29 (+0200), Max Reitz wrote : > On 11.06.2014 15:24, Beno=EEt Canet wrote: > >The to-replace-node-name is designed to allow repairing of broken Quor= um file. >=20 > "a broken Quorum file" or "broken Quorum files". >=20 > >This patch introduce a new class TestRepairQuorum testing that the fea= ture >=20 > *introduces >=20 > >works. > >Some further work will be done on QEMU to improve the robutness of the= tests. >=20 > *robustness >=20 > >Signed-off-by: Benoit Canet > >--- > > 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 ec470b2..c0480e1 100755 > >--- a/tests/qemu-iotests/041 > >+++ b/tests/qemu-iotests/041 > >@@ -28,6 +28,12 @@ target_backing_img =3D os.path.join(iotests.test_di= r, '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') > >+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.i= mg') > >+quorum_snapshot_file =3D os.path.join(iotests.test_dir, 'quorum_snaps= hot.img') > >+ > > class ImageMirroringTestCase(iotests.QMPTestCase): > > '''Abstract base class for image mirroring test cases''' > >@@ -42,8 +48,8 @@ class ImageMirroringTestCase(iotests.QMPTestCase): > > ready =3D True > > 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) >=20 > My Python is very bad (if existent at all), but is this > "drive=3Ddrive" really necessary? Wouldn't simply "drive" suffice? drive=3Ddrive means pass the drive variable in the parameter of the calle= e named drive. cancel_and_wait have multiple named parameters I need to pass the variabl= e into the right one. >=20 > > 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) > > result =3D self.vm.qmp('block-job-complete', device=3Ddrive) > > self.assert_qmp(result, 'return', {}) > >- event =3D self.wait_until_completed() > >+ event =3D self.wait_until_completed(drive=3Ddrive) > > self.assert_qmp(event, 'data/type', 'mirror') > > class TestSingleDrive(ImageMirroringTestCase): > >@@ -718,5 +724,187 @@ class TestUnbackedSource(ImageMirroringTestCase)= : > > self.complete_and_wait() > > self.assert_no_active_block_jobs() > >+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 man= ipulate > >+ # them > >+ opts =3D "node-name=3Dimg%i" % self.IMAGES.index(i) > >+ self.vm =3D self.vm.add_drive(i, opts) >=20 > Just an idea: As you are constantly swapping out img1, why don't you > write some data to img2 and img3 and different data to img1 to test > it all how it's supposed to work? Hmm we have another test for quorum file corruption repairing. This one is for major failure like the lost of a filer containing a parti= cular quorum file. >=20 > >+ > >+ 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", "= img2" ] } } > >+ 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 = images > >+ 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', sy= nc=3D'full', > >+ node_name=3D"repair0", > >+ replaces=3D"img1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.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) >=20 > Hm, why do you know this is at index 0? Because I ran the comand manually and it's predictible. It's all linked l= ist insertion and traversal. >=20 > >+ # 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_re= pair_img), > >+ 'target image does not match source after mir= roring') > >+ > >+ def test_cancel(self): > >+ self.assert_no_active_block_jobs() > >+ > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D"repair0", > >+ replaces=3D"img1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.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 = been > >+ # swapped out and unref > >+ result =3D self.vm.qmp('query-named-block-nodes') > >+ self.assert_qmp(result, 'return[0]/file', quorum_img3) >=20 > Why would img3 be affected at all? Aren't you trying to replace > img1? (Also, again, why index 0?) It means quorum_img3 should be at position 0 in the linked list: the last= inserted quorum file since we canceled the drive-mirror. >=20 > >+ 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', sy= nc=3D'full', > >+ node_name=3D"repair0", > >+ replaces=3D"img1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.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 = been > >+ # swapped out and unref > >+ self.assert_qmp(result, 'return[0]/file', quorum_img3) >=20 > Same here. same >=20 > >+ self.vm.shutdown() > >+ self.assertTrue(iotests.compare_images(quorum_img2, quorum_re= pair_img), > >+ 'target image does not match source after mir= roring') > >+ > >+ def test_pause(self): > >+ self.assert_no_active_block_jobs() > >+ > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D"repair0", > >+ replaces=3D"img1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.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_re= pair_img), > >+ 'target image does not match source after mir= roring') > >+ > >+ def test_medium_not_found(self): > >+ result =3D self.vm.qmp('drive-mirror', device=3D'ide1-cd0', s= ync=3D'full', >=20 > I don't know whether this device is supposed to exist forever, but > if it disappears from default configuration one day, TestSingleDrive > will break as well, so it's probably fine. >=20 > Max >=20 > >+ node_name=3D'repair0', > >+ replaces=3D'img1', > >+ target=3Dquorum_repair_img, format=3Diot= ests.imgfmt) > >+ self.assert_qmp(result, 'error/class', 'GenericError') > >+ > >+ def test_image_not_found(self): > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D'repair0', > >+ replaces=3D'img1', > >+ mode=3D'existing', > >+ target=3Dquorum_repair_img, format=3Diot= ests.imgfmt) > >+ self.assert_qmp(result, 'error/class', 'GenericError') > >+ > >+ def test_device_not_found(self): > >+ result =3D self.vm.qmp('drive-mirror', device=3D'nonexistent'= , sync=3D'full', > >+ node_name=3D'repair0', > >+ replaces=3D'img1', > >+ target=3Dquorum_repair_img, format=3Diot= ests.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=3Diot= ests.imgfmt) > >+ self.assert_qmp(result, 'error/class', 'GenericError') > >+ > >+ def test_no_node_name(self): > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ replaces=3D'img1', > >+ target=3Dquorum_repair_img, format=3Diot= ests.imgfmt) > >+ self.assert_qmp(result, 'error/class', 'GenericError') > >+ > >+ def test_unexistant_replaces(self): > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D'repair0', > >+ replaces=3D'img77', > >+ target=3Dquorum_repair_img, format=3Diot= ests.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= 'img1', > >+ snapshot_file=3Dquorum_snapshot_file, > >+ snapshot_node_name=3D"snap1"); > >+ > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D'repair0', > >+ replaces=3D"img1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.imgfmt) > >+ self.assert_qmp(result, 'error/class', 'GenericError') > >+ > >+ result =3D self.vm.qmp('drive-mirror', device=3D'quorum0', sy= nc=3D'full', > >+ node_name=3D'repair0', > >+ replaces=3D"snap1", > >+ target=3Dquorum_repair_img, format=3Diot= ests.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 6d9bee1..73e375a 100644 > >--- a/tests/qemu-iotests/041.out > >+++ b/tests/qemu-iotests/041.out > >@@ -1,5 +1,5 @@ > >-........................... > >+...................................... > > --------------------------------------------------------------------= -- > >-Ran 27 tests > >+Ran 38 tests > > OK >=20