qemu-iotests test case 148 already had some code for skipping the test if quorum support is missing, but it didn't work in all cases. TestQuorumEvents.setUp() gets run before the actual test class (which contains the skipping code) and tries to start qemu with a drive using the quorum driver. For some reason this works fine when using qcow2, but fails for raw. As the entire test case requires quorum, just check for availability before even starting the test suite. Introduce a verify_quorum() function in iotests.py for this purpose so future test cases can make use of it. Signed-off-by: Sascha Silbe <silbe@linux.vnet.ibm.com> Reviewed-by: Bo Tu <tubo@linux.vnet.ibm.com> Message-id: 1459848109-29756-5-git-send-email-silbe@linux.vnet.ibm.com Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
141 lines
5.2 KiB
Python
141 lines
5.2 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Test the rate limit of QMP events
|
|
#
|
|
# Copyright (C) 2016 Igalia, S.L.
|
|
# Author: Alberto Garcia <berto@igalia.com>
|
|
#
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
import os
|
|
import iotests
|
|
|
|
imgs = (os.path.join(iotests.test_dir, 'quorum0.img'),
|
|
os.path.join(iotests.test_dir, 'quorum1.img'),
|
|
os.path.join(iotests.test_dir, 'quorum2.img'))
|
|
|
|
img_conf = (os.path.join(iotests.test_dir, 'quorum0.conf'),
|
|
os.path.join(iotests.test_dir, 'quorum1.conf'),
|
|
os.path.join(iotests.test_dir, 'quorum2.conf'))
|
|
|
|
event_rate = 1000000000
|
|
sector_size = 512
|
|
offset = 10
|
|
|
|
class TestQuorumEvents(iotests.QMPTestCase):
|
|
read_pattern = 'quorum'
|
|
|
|
def create_blkdebug_file(self, blkdebug_file, bad_sector):
|
|
file = open(blkdebug_file, 'w')
|
|
file.write('''
|
|
[inject-error]
|
|
event = "read_aio"
|
|
errno = "5"
|
|
sector = "%d"
|
|
''' % bad_sector)
|
|
file.close()
|
|
|
|
def setUp(self):
|
|
driveopts = ['driver=quorum', 'vote-threshold=2']
|
|
driveopts.append('read-pattern=%s' % self.read_pattern)
|
|
for i in range(len(imgs)):
|
|
iotests.qemu_img('create', '-f', iotests.imgfmt, imgs[i], '1M')
|
|
self.create_blkdebug_file(img_conf[i], i + offset)
|
|
driveopts.append('children.%d.driver=%s' % (i, iotests.imgfmt))
|
|
driveopts.append('children.%d.file.driver=blkdebug' % i)
|
|
driveopts.append('children.%d.file.config=%s' % (i, img_conf[i]))
|
|
driveopts.append('children.%d.file.image.filename=%s' % (i, imgs[i]))
|
|
driveopts.append('children.%d.node-name=img%d' % (i, i))
|
|
self.vm = iotests.VM()
|
|
self.vm.add_drive(None, opts = ','.join(driveopts))
|
|
self.vm.launch()
|
|
|
|
def tearDown(self):
|
|
self.vm.shutdown()
|
|
for i in range(len(imgs)):
|
|
os.remove(imgs[i])
|
|
os.remove(img_conf[i])
|
|
|
|
def do_check_event(self, node, sector = 0):
|
|
if node == None:
|
|
self.assertEqual(self.vm.get_qmp_event(), None)
|
|
return
|
|
|
|
for event in self.vm.get_qmp_events(wait=True):
|
|
if event['event'] == 'QUORUM_REPORT_BAD':
|
|
self.assert_qmp(event, 'data/node-name', node)
|
|
self.assert_qmp(event, 'data/sector-num', sector)
|
|
|
|
def testQuorum(self):
|
|
# Generate an error and get an event
|
|
self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
|
|
(offset * sector_size, sector_size))
|
|
self.vm.qtest("clock_step 10")
|
|
self.do_check_event('img0', offset)
|
|
|
|
# I/O errors in the same child: only one event is emitted
|
|
delay = 10
|
|
for i in range(3):
|
|
self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
|
|
(offset * sector_size, sector_size))
|
|
self.vm.qtest("clock_step %d" % delay)
|
|
self.do_check_event(None)
|
|
|
|
# Wait enough so the event is finally emitted
|
|
self.vm.qtest("clock_step %d" % (2 * event_rate))
|
|
self.do_check_event('img0', offset)
|
|
|
|
# I/O errors in the same child: all events are emitted
|
|
delay = 2 * event_rate
|
|
for i in range(3):
|
|
self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
|
|
(offset * sector_size, sector_size))
|
|
self.vm.qtest("clock_step %d" % delay)
|
|
self.do_check_event('img0', offset)
|
|
|
|
# I/O errors in different children: all events are emitted
|
|
delay = 10
|
|
for i in range(len(imgs)):
|
|
self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
|
|
((offset + i) * sector_size, sector_size))
|
|
self.vm.qtest("clock_step %d" % delay)
|
|
# In fifo mode only errors in the first child are detected
|
|
if i > 0 and self.read_pattern == 'fifo':
|
|
self.do_check_event(None)
|
|
else:
|
|
self.do_check_event('img%d' % i, offset + i)
|
|
|
|
# I/O errors in different children: all events are emitted
|
|
delay = 2 * event_rate
|
|
for i in range(len(imgs)):
|
|
self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
|
|
((offset + i) * sector_size, sector_size))
|
|
self.vm.qtest("clock_step %d" % delay)
|
|
# In fifo mode only errors in the first child are detected
|
|
if i > 0 and self.read_pattern == 'fifo':
|
|
self.do_check_event(None)
|
|
else:
|
|
self.do_check_event('img%d' % i, offset + i)
|
|
|
|
# No more pending events
|
|
self.do_check_event(None)
|
|
|
|
class TestFifoQuorumEvents(TestQuorumEvents):
|
|
read_pattern = 'fifo'
|
|
|
|
if __name__ == '__main__':
|
|
iotests.verify_quorum()
|
|
iotests.main(supported_fmts=["raw"])
|