xref: /openbmc/qemu/tests/qemu-iotests/030 (revision 90f0b71153c6a85d03967244b9889f892841d835)
137ce63ebSStefan Hajnoczi#!/usr/bin/env python
237ce63ebSStefan Hajnoczi#
337ce63ebSStefan Hajnoczi# Tests for image streaming.
437ce63ebSStefan Hajnoczi#
537ce63ebSStefan Hajnoczi# Copyright (C) 2012 IBM Corp.
637ce63ebSStefan Hajnoczi#
737ce63ebSStefan Hajnoczi# This program is free software; you can redistribute it and/or modify
837ce63ebSStefan Hajnoczi# it under the terms of the GNU General Public License as published by
937ce63ebSStefan Hajnoczi# the Free Software Foundation; either version 2 of the License, or
1037ce63ebSStefan Hajnoczi# (at your option) any later version.
1137ce63ebSStefan Hajnoczi#
1237ce63ebSStefan Hajnoczi# This program is distributed in the hope that it will be useful,
1337ce63ebSStefan Hajnoczi# but WITHOUT ANY WARRANTY; without even the implied warranty of
1437ce63ebSStefan Hajnoczi# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1537ce63ebSStefan Hajnoczi# GNU General Public License for more details.
1637ce63ebSStefan Hajnoczi#
1737ce63ebSStefan Hajnoczi# You should have received a copy of the GNU General Public License
1837ce63ebSStefan Hajnoczi# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1937ce63ebSStefan Hajnoczi#
2037ce63ebSStefan Hajnoczi
210c817347SPaolo Bonziniimport time
2237ce63ebSStefan Hajnocziimport os
2337ce63ebSStefan Hajnocziimport iotests
2437ce63ebSStefan Hajnoczifrom iotests import qemu_img, qemu_io
25ab68cdfaSPaolo Bonziniimport struct
2637ce63ebSStefan Hajnoczi
2737ce63ebSStefan Hajnoczibacking_img = os.path.join(iotests.test_dir, 'backing.img')
286e343609SPaolo Bonzinimid_img = os.path.join(iotests.test_dir, 'mid.img')
2937ce63ebSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img')
3037ce63ebSStefan Hajnoczi
3137ce63ebSStefan Hajnocziclass ImageStreamingTestCase(iotests.QMPTestCase):
3237ce63ebSStefan Hajnoczi    '''Abstract base class for image streaming test cases'''
3337ce63ebSStefan Hajnoczi
3437ce63ebSStefan Hajnoczi    def assert_no_active_streams(self):
3537ce63ebSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
3637ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', [])
3737ce63ebSStefan Hajnoczi
38e425306aSStefan Hajnoczi    def cancel_and_wait(self, drive='drive0'):
39e425306aSStefan Hajnoczi        '''Cancel a block job and wait for it to finish'''
40e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-cancel', device=drive)
41e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
42e425306aSStefan Hajnoczi
43e425306aSStefan Hajnoczi        cancelled = False
44e425306aSStefan Hajnoczi        while not cancelled:
45e425306aSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
46e425306aSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_CANCELLED':
47e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
48e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', drive)
49e425306aSStefan Hajnoczi                    cancelled = True
50e425306aSStefan Hajnoczi
51e425306aSStefan Hajnoczi        self.assert_no_active_streams()
52e425306aSStefan Hajnoczi
53ab68cdfaSPaolo Bonzini    def create_image(self, name, size):
54ab68cdfaSPaolo Bonzini        file = open(name, 'w')
55ab68cdfaSPaolo Bonzini        i = 0
56ab68cdfaSPaolo Bonzini        while i < size:
57ab68cdfaSPaolo Bonzini            sector = struct.pack('>l504xl', i / 512, i / 512)
58ab68cdfaSPaolo Bonzini            file.write(sector)
59ab68cdfaSPaolo Bonzini            i = i + 512
60ab68cdfaSPaolo Bonzini        file.close()
61ab68cdfaSPaolo Bonzini
62ab68cdfaSPaolo Bonzini
6337ce63ebSStefan Hajnocziclass TestSingleDrive(ImageStreamingTestCase):
6437ce63ebSStefan Hajnoczi    image_len = 1 * 1024 * 1024 # MB
6537ce63ebSStefan Hajnoczi
6637ce63ebSStefan Hajnoczi    def setUp(self):
67ab68cdfaSPaolo Bonzini        self.create_image(backing_img, TestSingleDrive.image_len)
686e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
696e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
7037ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
7137ce63ebSStefan Hajnoczi        self.vm.launch()
7237ce63ebSStefan Hajnoczi
7337ce63ebSStefan Hajnoczi    def tearDown(self):
7437ce63ebSStefan Hajnoczi        self.vm.shutdown()
7537ce63ebSStefan Hajnoczi        os.remove(test_img)
766e343609SPaolo Bonzini        os.remove(mid_img)
7737ce63ebSStefan Hajnoczi        os.remove(backing_img)
7837ce63ebSStefan Hajnoczi
7937ce63ebSStefan Hajnoczi    def test_stream(self):
8037ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
8137ce63ebSStefan Hajnoczi
82db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
8337ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
8437ce63ebSStefan Hajnoczi
8537ce63ebSStefan Hajnoczi        completed = False
8637ce63ebSStefan Hajnoczi        while not completed:
8737ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
8837ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
8937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
9037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
9137ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
9237ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
9337ce63ebSStefan Hajnoczi                    completed = True
9437ce63ebSStefan Hajnoczi
9537ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
96863a5d04SPaolo Bonzini        self.vm.shutdown()
9737ce63ebSStefan Hajnoczi
98efcc7a23SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
99efcc7a23SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
100efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
10137ce63ebSStefan Hajnoczi
1020c817347SPaolo Bonzini    def test_stream_pause(self):
1030c817347SPaolo Bonzini        self.assert_no_active_streams()
1040c817347SPaolo Bonzini
1050c817347SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
1060c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1070c817347SPaolo Bonzini
1080c817347SPaolo Bonzini        result = self.vm.qmp('block-job-pause', device='drive0')
1090c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1100c817347SPaolo Bonzini
1110c817347SPaolo Bonzini        time.sleep(1)
1120c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
1130c817347SPaolo Bonzini        offset = self.dictpath(result, 'return[0]/offset')
1140c817347SPaolo Bonzini
1150c817347SPaolo Bonzini        time.sleep(1)
1160c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
1170c817347SPaolo Bonzini        self.assert_qmp(result, 'return[0]/offset', offset)
1180c817347SPaolo Bonzini
1190c817347SPaolo Bonzini        result = self.vm.qmp('block-job-resume', device='drive0')
1200c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1210c817347SPaolo Bonzini
1220c817347SPaolo Bonzini        completed = False
1230c817347SPaolo Bonzini        while not completed:
1240c817347SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1250c817347SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1260c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1270c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1280c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1290c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1300c817347SPaolo Bonzini                    completed = True
1310c817347SPaolo Bonzini
1320c817347SPaolo Bonzini        self.assert_no_active_streams()
1330c817347SPaolo Bonzini        self.vm.shutdown()
1340c817347SPaolo Bonzini
1350c817347SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
1360c817347SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1370c817347SPaolo Bonzini                         'image file map does not match backing file after streaming')
1380c817347SPaolo Bonzini
1396e343609SPaolo Bonzini    def test_stream_partial(self):
1406e343609SPaolo Bonzini        self.assert_no_active_streams()
1416e343609SPaolo Bonzini
1426e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
1436e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1446e343609SPaolo Bonzini
1456e343609SPaolo Bonzini        completed = False
1466e343609SPaolo Bonzini        while not completed:
1476e343609SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1486e343609SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1496e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1506e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1516e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1526e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1536e343609SPaolo Bonzini                    completed = True
1546e343609SPaolo Bonzini
1556e343609SPaolo Bonzini        self.assert_no_active_streams()
1566e343609SPaolo Bonzini        self.vm.shutdown()
1576e343609SPaolo Bonzini
1586e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
1596e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1606e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1616e343609SPaolo Bonzini
16237ce63ebSStefan Hajnoczi    def test_device_not_found(self):
163db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
16437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
16537ce63ebSStefan Hajnoczi
166774a8850SStefan Hajnoczi
167774a8850SStefan Hajnocziclass TestSmallerBackingFile(ImageStreamingTestCase):
168774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
169774a8850SStefan Hajnoczi    image_len = 2 * backing_len
170774a8850SStefan Hajnoczi
171774a8850SStefan Hajnoczi    def setUp(self):
172774a8850SStefan Hajnoczi        self.create_image(backing_img, self.backing_len)
173774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
174774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
175774a8850SStefan Hajnoczi        self.vm.launch()
176774a8850SStefan Hajnoczi
177774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
178774a8850SStefan Hajnoczi    # end of the backing file is reached.
179774a8850SStefan Hajnoczi    def test_stream(self):
180774a8850SStefan Hajnoczi        self.assert_no_active_streams()
181774a8850SStefan Hajnoczi
182774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
183774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
184774a8850SStefan Hajnoczi
185774a8850SStefan Hajnoczi        completed = False
186774a8850SStefan Hajnoczi        while not completed:
187774a8850SStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
188774a8850SStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
189774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
190774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
191774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
192774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
193774a8850SStefan Hajnoczi                    completed = True
194774a8850SStefan Hajnoczi
195774a8850SStefan Hajnoczi        self.assert_no_active_streams()
196774a8850SStefan Hajnoczi        self.vm.shutdown()
197774a8850SStefan Hajnoczi
198*90f0b711SPaolo Bonziniclass TestErrors(ImageStreamingTestCase):
199*90f0b711SPaolo Bonzini    image_len = 2 * 1024 * 1024 # MB
200*90f0b711SPaolo Bonzini
201*90f0b711SPaolo Bonzini    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
202*90f0b711SPaolo Bonzini    STREAM_BUFFER_SIZE = 512 * 1024
203*90f0b711SPaolo Bonzini
204*90f0b711SPaolo Bonzini    def create_blkdebug_file(self, name, event, errno):
205*90f0b711SPaolo Bonzini        file = open(name, 'w')
206*90f0b711SPaolo Bonzini        file.write('''
207*90f0b711SPaolo Bonzini[inject-error]
208*90f0b711SPaolo Bonzinistate = "1"
209*90f0b711SPaolo Bonzinievent = "%s"
210*90f0b711SPaolo Bonzinierrno = "%d"
211*90f0b711SPaolo Bonziniimmediately = "off"
212*90f0b711SPaolo Bonzinionce = "on"
213*90f0b711SPaolo Bonzinisector = "%d"
214*90f0b711SPaolo Bonzini
215*90f0b711SPaolo Bonzini[set-state]
216*90f0b711SPaolo Bonzinistate = "1"
217*90f0b711SPaolo Bonzinievent = "%s"
218*90f0b711SPaolo Bonzininew_state = "2"
219*90f0b711SPaolo Bonzini
220*90f0b711SPaolo Bonzini[set-state]
221*90f0b711SPaolo Bonzinistate = "2"
222*90f0b711SPaolo Bonzinievent = "%s"
223*90f0b711SPaolo Bonzininew_state = "1"
224*90f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
225*90f0b711SPaolo Bonzini        file.close()
226*90f0b711SPaolo Bonzini
227*90f0b711SPaolo Bonziniclass TestEIO(TestErrors):
228*90f0b711SPaolo Bonzini    def setUp(self):
229*90f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
230*90f0b711SPaolo Bonzini        self.create_image(backing_img, TestErrors.image_len)
231*90f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
232*90f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
233*90f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
234*90f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
235*90f0b711SPaolo Bonzini                 test_img)
236*90f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
237*90f0b711SPaolo Bonzini        self.vm.launch()
238*90f0b711SPaolo Bonzini
239*90f0b711SPaolo Bonzini    def tearDown(self):
240*90f0b711SPaolo Bonzini        self.vm.shutdown()
241*90f0b711SPaolo Bonzini        os.remove(test_img)
242*90f0b711SPaolo Bonzini        os.remove(backing_img)
243*90f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
244*90f0b711SPaolo Bonzini
245*90f0b711SPaolo Bonzini    def test_report(self):
246*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
247*90f0b711SPaolo Bonzini
248*90f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
249*90f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
250*90f0b711SPaolo Bonzini
251*90f0b711SPaolo Bonzini        completed = False
252*90f0b711SPaolo Bonzini        error = False
253*90f0b711SPaolo Bonzini        while not completed:
254*90f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
255*90f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
256*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
257*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
258*90f0b711SPaolo Bonzini                    error = True
259*90f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
260*90f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
261*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
262*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
263*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
264*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
265*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
266*90f0b711SPaolo Bonzini                    completed = True
267*90f0b711SPaolo Bonzini
268*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
269*90f0b711SPaolo Bonzini        self.vm.shutdown()
270*90f0b711SPaolo Bonzini
271*90f0b711SPaolo Bonzini    def test_ignore(self):
272*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
273*90f0b711SPaolo Bonzini
274*90f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
275*90f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
276*90f0b711SPaolo Bonzini
277*90f0b711SPaolo Bonzini        error = False
278*90f0b711SPaolo Bonzini        completed = False
279*90f0b711SPaolo Bonzini        while not completed:
280*90f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
281*90f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
282*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
283*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
284*90f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
285*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
286*90f0b711SPaolo Bonzini                    error = True
287*90f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
288*90f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
289*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
290*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
291*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
292*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
293*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
294*90f0b711SPaolo Bonzini                    completed = True
295*90f0b711SPaolo Bonzini
296*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
297*90f0b711SPaolo Bonzini        self.vm.shutdown()
298*90f0b711SPaolo Bonzini
299*90f0b711SPaolo Bonzini    def test_stop(self):
300*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
301*90f0b711SPaolo Bonzini
302*90f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
303*90f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
304*90f0b711SPaolo Bonzini
305*90f0b711SPaolo Bonzini        error = False
306*90f0b711SPaolo Bonzini        completed = False
307*90f0b711SPaolo Bonzini        while not completed:
308*90f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
309*90f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
310*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
311*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
312*90f0b711SPaolo Bonzini
313*90f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
314*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
315*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
316*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'failed')
317*90f0b711SPaolo Bonzini
318*90f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
319*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
320*90f0b711SPaolo Bonzini
321*90f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
322*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
323*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
324*90f0b711SPaolo Bonzini                    error = True
325*90f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
326*90f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
327*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
328*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
329*90f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
330*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
331*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
332*90f0b711SPaolo Bonzini                    completed = True
333*90f0b711SPaolo Bonzini
334*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
335*90f0b711SPaolo Bonzini        self.vm.shutdown()
336*90f0b711SPaolo Bonzini
337*90f0b711SPaolo Bonzini    def test_enospc(self):
338*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
339*90f0b711SPaolo Bonzini
340*90f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
341*90f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
342*90f0b711SPaolo Bonzini
343*90f0b711SPaolo Bonzini        completed = False
344*90f0b711SPaolo Bonzini        error = False
345*90f0b711SPaolo Bonzini        while not completed:
346*90f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
347*90f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
348*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
349*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
350*90f0b711SPaolo Bonzini                    error = True
351*90f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
352*90f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
353*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
354*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
355*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
356*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
357*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
358*90f0b711SPaolo Bonzini                    completed = True
359*90f0b711SPaolo Bonzini
360*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
361*90f0b711SPaolo Bonzini        self.vm.shutdown()
362*90f0b711SPaolo Bonzini
363*90f0b711SPaolo Bonziniclass TestENOSPC(TestErrors):
364*90f0b711SPaolo Bonzini    def setUp(self):
365*90f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
366*90f0b711SPaolo Bonzini        self.create_image(backing_img, TestErrors.image_len)
367*90f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
368*90f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
369*90f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
370*90f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
371*90f0b711SPaolo Bonzini                 test_img)
372*90f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
373*90f0b711SPaolo Bonzini        self.vm.launch()
374*90f0b711SPaolo Bonzini
375*90f0b711SPaolo Bonzini    def tearDown(self):
376*90f0b711SPaolo Bonzini        self.vm.shutdown()
377*90f0b711SPaolo Bonzini        os.remove(test_img)
378*90f0b711SPaolo Bonzini        os.remove(backing_img)
379*90f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
380*90f0b711SPaolo Bonzini
381*90f0b711SPaolo Bonzini    def test_enospc(self):
382*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
383*90f0b711SPaolo Bonzini
384*90f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
385*90f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
386*90f0b711SPaolo Bonzini
387*90f0b711SPaolo Bonzini        error = False
388*90f0b711SPaolo Bonzini        completed = False
389*90f0b711SPaolo Bonzini        while not completed:
390*90f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
391*90f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
392*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
393*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
394*90f0b711SPaolo Bonzini
395*90f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
396*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
397*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
398*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')
399*90f0b711SPaolo Bonzini
400*90f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
401*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
402*90f0b711SPaolo Bonzini
403*90f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
404*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
405*90f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
406*90f0b711SPaolo Bonzini                    error = True
407*90f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
408*90f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
409*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
410*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
411*90f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
412*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
413*90f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
414*90f0b711SPaolo Bonzini                    completed = True
415*90f0b711SPaolo Bonzini
416*90f0b711SPaolo Bonzini        self.assert_no_active_streams()
417*90f0b711SPaolo Bonzini        self.vm.shutdown()
418774a8850SStefan Hajnoczi
41937ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase):
42037ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
42137ce63ebSStefan Hajnoczi
42237ce63ebSStefan Hajnoczi    def setUp(self):
42337ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
42437ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
42537ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
42637ce63ebSStefan Hajnoczi        self.vm.launch()
42737ce63ebSStefan Hajnoczi
42837ce63ebSStefan Hajnoczi    def tearDown(self):
42937ce63ebSStefan Hajnoczi        self.vm.shutdown()
43037ce63ebSStefan Hajnoczi        os.remove(test_img)
43137ce63ebSStefan Hajnoczi        os.remove(backing_img)
43237ce63ebSStefan Hajnoczi
43337ce63ebSStefan Hajnoczi    def test_stream_stop(self):
43437ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
43537ce63ebSStefan Hajnoczi
436db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
43737ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
43837ce63ebSStefan Hajnoczi
4390fd05e8dSPaolo Bonzini        time.sleep(0.1)
44037ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
44137ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
44237ce63ebSStefan Hajnoczi
443e425306aSStefan Hajnoczi        self.cancel_and_wait()
44437ce63ebSStefan Hajnoczi
44537ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase):
44637ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
44737ce63ebSStefan Hajnoczi
44837ce63ebSStefan Hajnoczi    def setUp(self):
44937ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
45037ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
45137ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
45237ce63ebSStefan Hajnoczi        self.vm.launch()
45337ce63ebSStefan Hajnoczi
45437ce63ebSStefan Hajnoczi    def tearDown(self):
45537ce63ebSStefan Hajnoczi        self.vm.shutdown()
45637ce63ebSStefan Hajnoczi        os.remove(test_img)
45737ce63ebSStefan Hajnoczi        os.remove(backing_img)
45837ce63ebSStefan Hajnoczi
459e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
460e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
461e425306aSStefan Hajnoczi    def perf_test_throughput(self):
46237ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
46337ce63ebSStefan Hajnoczi
464db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
46537ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
46637ce63ebSStefan Hajnoczi
467e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
46837ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
46937ce63ebSStefan Hajnoczi
47037ce63ebSStefan Hajnoczi        completed = False
47137ce63ebSStefan Hajnoczi        while not completed:
47237ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
47337ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
47437ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
47537ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
47637ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
47737ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
47837ce63ebSStefan Hajnoczi                    completed = True
47937ce63ebSStefan Hajnoczi
48037ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
48137ce63ebSStefan Hajnoczi
482e425306aSStefan Hajnoczi    def test_set_speed(self):
483e425306aSStefan Hajnoczi        self.assert_no_active_streams()
484e425306aSStefan Hajnoczi
485e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
486e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
487e425306aSStefan Hajnoczi
488e425306aSStefan Hajnoczi        # Default speed is 0
489e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
490e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
491e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
492e425306aSStefan Hajnoczi
493e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
494e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
495e425306aSStefan Hajnoczi
496e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
497e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
498e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
499e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
500e425306aSStefan Hajnoczi
501e425306aSStefan Hajnoczi        self.cancel_and_wait()
502e425306aSStefan Hajnoczi
503e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
504e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
505e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
506e425306aSStefan Hajnoczi
507e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
508e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
509e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
510e425306aSStefan Hajnoczi
511e425306aSStefan Hajnoczi        self.cancel_and_wait()
512e425306aSStefan Hajnoczi
513e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
514e425306aSStefan Hajnoczi        self.assert_no_active_streams()
515e425306aSStefan Hajnoczi
516e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
51758c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
518e425306aSStefan Hajnoczi
519e425306aSStefan Hajnoczi        self.assert_no_active_streams()
520e425306aSStefan Hajnoczi
521e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
522e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
523e425306aSStefan Hajnoczi
524e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
52558c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
526e425306aSStefan Hajnoczi
527e425306aSStefan Hajnoczi        self.cancel_and_wait()
528e425306aSStefan Hajnoczi
52937ce63ebSStefan Hajnocziif __name__ == '__main__':
53037ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
531