]>
Commit | Line | Data |
---|---|---|
903cb1bf | 1 | #!/usr/bin/env python3 |
9dd003a9 | 2 | # group: rw quick |
7223c48c AG |
3 | # |
4 | # Test the rate limit of QMP events | |
5 | # | |
6 | # Copyright (C) 2016 Igalia, S.L. | |
7 | # Author: Alberto Garcia <[email protected]> | |
8 | # | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 2 of the License, or | |
12 | # (at your option) any later version. | |
13 | # | |
14 | # This program is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | # | |
22 | ||
23 | import os | |
24 | import iotests | |
25 | ||
26 | imgs = (os.path.join(iotests.test_dir, 'quorum0.img'), | |
27 | os.path.join(iotests.test_dir, 'quorum1.img'), | |
28 | os.path.join(iotests.test_dir, 'quorum2.img')) | |
29 | ||
30 | img_conf = (os.path.join(iotests.test_dir, 'quorum0.conf'), | |
31 | os.path.join(iotests.test_dir, 'quorum1.conf'), | |
32 | os.path.join(iotests.test_dir, 'quorum2.conf')) | |
33 | ||
34 | event_rate = 1000000000 | |
35 | sector_size = 512 | |
36 | offset = 10 | |
37 | ||
38 | class TestQuorumEvents(iotests.QMPTestCase): | |
509565f3 | 39 | read_pattern = 'quorum' |
7223c48c AG |
40 | |
41 | def create_blkdebug_file(self, blkdebug_file, bad_sector): | |
42 | file = open(blkdebug_file, 'w') | |
43 | file.write(''' | |
44 | [inject-error] | |
45 | event = "read_aio" | |
46 | errno = "5" | |
47 | sector = "%d" | |
48 | ''' % bad_sector) | |
49 | file.close() | |
50 | ||
50bb041a | 51 | @iotests.skip_if_unsupported(['quorum']) |
7223c48c AG |
52 | def setUp(self): |
53 | driveopts = ['driver=quorum', 'vote-threshold=2'] | |
509565f3 | 54 | driveopts.append('read-pattern=%s' % self.read_pattern) |
7223c48c AG |
55 | for i in range(len(imgs)): |
56 | iotests.qemu_img('create', '-f', iotests.imgfmt, imgs[i], '1M') | |
57 | self.create_blkdebug_file(img_conf[i], i + offset) | |
58 | driveopts.append('children.%d.driver=%s' % (i, iotests.imgfmt)) | |
59 | driveopts.append('children.%d.file.driver=blkdebug' % i) | |
60 | driveopts.append('children.%d.file.config=%s' % (i, img_conf[i])) | |
61 | driveopts.append('children.%d.file.image.filename=%s' % (i, imgs[i])) | |
62 | driveopts.append('children.%d.node-name=img%d' % (i, i)) | |
63 | self.vm = iotests.VM() | |
64 | self.vm.add_drive(None, opts = ','.join(driveopts)) | |
65 | self.vm.launch() | |
66 | ||
67 | def tearDown(self): | |
68 | self.vm.shutdown() | |
69 | for i in range(len(imgs)): | |
70 | os.remove(imgs[i]) | |
71 | os.remove(img_conf[i]) | |
72 | ||
73 | def do_check_event(self, node, sector = 0): | |
74 | if node == None: | |
75 | self.assertEqual(self.vm.get_qmp_event(), None) | |
76 | return | |
77 | ||
78 | for event in self.vm.get_qmp_events(wait=True): | |
79 | if event['event'] == 'QUORUM_REPORT_BAD': | |
80 | self.assert_qmp(event, 'data/node-name', node) | |
81 | self.assert_qmp(event, 'data/sector-num', sector) | |
82 | ||
83 | def testQuorum(self): | |
7223c48c AG |
84 | # Generate an error and get an event |
85 | self.vm.hmp_qemu_io("drive0", "aio_read %d %d" % | |
86 | (offset * sector_size, sector_size)) | |
87 | self.vm.qtest("clock_step 10") | |
88 | self.do_check_event('img0', offset) | |
89 | ||
90 | # I/O errors in the same child: only one event is emitted | |
91 | delay = 10 | |
92 | for i in range(3): | |
93 | self.vm.hmp_qemu_io("drive0", "aio_read %d %d" % | |
94 | (offset * sector_size, sector_size)) | |
95 | self.vm.qtest("clock_step %d" % delay) | |
96 | self.do_check_event(None) | |
97 | ||
98 | # Wait enough so the event is finally emitted | |
99 | self.vm.qtest("clock_step %d" % (2 * event_rate)) | |
100 | self.do_check_event('img0', offset) | |
101 | ||
102 | # I/O errors in the same child: all events are emitted | |
103 | delay = 2 * event_rate | |
104 | for i in range(3): | |
105 | self.vm.hmp_qemu_io("drive0", "aio_read %d %d" % | |
106 | (offset * sector_size, sector_size)) | |
107 | self.vm.qtest("clock_step %d" % delay) | |
108 | self.do_check_event('img0', offset) | |
109 | ||
110 | # I/O errors in different children: all events are emitted | |
111 | delay = 10 | |
112 | for i in range(len(imgs)): | |
113 | self.vm.hmp_qemu_io("drive0", "aio_read %d %d" % | |
114 | ((offset + i) * sector_size, sector_size)) | |
115 | self.vm.qtest("clock_step %d" % delay) | |
509565f3 AG |
116 | # In fifo mode only errors in the first child are detected |
117 | if i > 0 and self.read_pattern == 'fifo': | |
118 | self.do_check_event(None) | |
119 | else: | |
120 | self.do_check_event('img%d' % i, offset + i) | |
7223c48c AG |
121 | |
122 | # I/O errors in different children: all events are emitted | |
123 | delay = 2 * event_rate | |
124 | for i in range(len(imgs)): | |
125 | self.vm.hmp_qemu_io("drive0", "aio_read %d %d" % | |
126 | ((offset + i) * sector_size, sector_size)) | |
127 | self.vm.qtest("clock_step %d" % delay) | |
509565f3 AG |
128 | # In fifo mode only errors in the first child are detected |
129 | if i > 0 and self.read_pattern == 'fifo': | |
130 | self.do_check_event(None) | |
131 | else: | |
132 | self.do_check_event('img%d' % i, offset + i) | |
7223c48c AG |
133 | |
134 | # No more pending events | |
135 | self.do_check_event(None) | |
136 | ||
509565f3 AG |
137 | class TestFifoQuorumEvents(TestQuorumEvents): |
138 | read_pattern = 'fifo' | |
139 | ||
7223c48c | 140 | if __name__ == '__main__': |
3f647b51 | 141 | iotests.verify_quorum() |
103cbc77 HR |
142 | iotests.main(supported_fmts=["raw"], |
143 | supported_protocols=["file"]) |