#!/usr/bin/env python # # Test the rate limit of QMP events # # Copyright (C) 2016 Igalia, S.L. # Author: Alberto Garcia # # 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 . # 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"])