xref: /qemu/tests/qemu-iotests/030 (revision ecc1c88e)
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
34e425306aSStefan Hajnoczi    def cancel_and_wait(self, drive='drive0'):
35e425306aSStefan Hajnoczi        '''Cancel a block job and wait for it to finish'''
36e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-cancel', device=drive)
37e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
38e425306aSStefan Hajnoczi
39e425306aSStefan Hajnoczi        cancelled = False
40e425306aSStefan Hajnoczi        while not cancelled:
41e425306aSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
42e425306aSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_CANCELLED':
43e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
44e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', drive)
45e425306aSStefan Hajnoczi                    cancelled = True
46e425306aSStefan Hajnoczi
47*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
48e425306aSStefan Hajnoczi
49ab68cdfaSPaolo Bonzini    def create_image(self, name, size):
50ab68cdfaSPaolo Bonzini        file = open(name, 'w')
51ab68cdfaSPaolo Bonzini        i = 0
52ab68cdfaSPaolo Bonzini        while i < size:
53ab68cdfaSPaolo Bonzini            sector = struct.pack('>l504xl', i / 512, i / 512)
54ab68cdfaSPaolo Bonzini            file.write(sector)
55ab68cdfaSPaolo Bonzini            i = i + 512
56ab68cdfaSPaolo Bonzini        file.close()
57ab68cdfaSPaolo Bonzini
58ab68cdfaSPaolo Bonzini
5937ce63ebSStefan Hajnocziclass TestSingleDrive(ImageStreamingTestCase):
6037ce63ebSStefan Hajnoczi    image_len = 1 * 1024 * 1024 # MB
6137ce63ebSStefan Hajnoczi
6237ce63ebSStefan Hajnoczi    def setUp(self):
63ab68cdfaSPaolo Bonzini        self.create_image(backing_img, TestSingleDrive.image_len)
646e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
656e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
6637ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
6737ce63ebSStefan Hajnoczi        self.vm.launch()
6837ce63ebSStefan Hajnoczi
6937ce63ebSStefan Hajnoczi    def tearDown(self):
7037ce63ebSStefan Hajnoczi        self.vm.shutdown()
7137ce63ebSStefan Hajnoczi        os.remove(test_img)
726e343609SPaolo Bonzini        os.remove(mid_img)
7337ce63ebSStefan Hajnoczi        os.remove(backing_img)
7437ce63ebSStefan Hajnoczi
7537ce63ebSStefan Hajnoczi    def test_stream(self):
76*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
7737ce63ebSStefan Hajnoczi
78db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
7937ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
8037ce63ebSStefan Hajnoczi
8137ce63ebSStefan Hajnoczi        completed = False
8237ce63ebSStefan Hajnoczi        while not completed:
8337ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
8437ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
8537ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
8637ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
8737ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
8837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
8937ce63ebSStefan Hajnoczi                    completed = True
9037ce63ebSStefan Hajnoczi
91*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
92863a5d04SPaolo Bonzini        self.vm.shutdown()
9337ce63ebSStefan Hajnoczi
94efcc7a23SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
95efcc7a23SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
96efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
9737ce63ebSStefan Hajnoczi
980c817347SPaolo Bonzini    def test_stream_pause(self):
99*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1000c817347SPaolo Bonzini
1010c817347SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
1020c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1030c817347SPaolo Bonzini
1040c817347SPaolo Bonzini        result = self.vm.qmp('block-job-pause', device='drive0')
1050c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1060c817347SPaolo Bonzini
1070c817347SPaolo Bonzini        time.sleep(1)
1080c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
1090c817347SPaolo Bonzini        offset = self.dictpath(result, 'return[0]/offset')
1100c817347SPaolo Bonzini
1110c817347SPaolo Bonzini        time.sleep(1)
1120c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
1130c817347SPaolo Bonzini        self.assert_qmp(result, 'return[0]/offset', offset)
1140c817347SPaolo Bonzini
1150c817347SPaolo Bonzini        result = self.vm.qmp('block-job-resume', device='drive0')
1160c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1170c817347SPaolo Bonzini
1180c817347SPaolo Bonzini        completed = False
1190c817347SPaolo Bonzini        while not completed:
1200c817347SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1210c817347SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1220c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1230c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1240c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1250c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1260c817347SPaolo Bonzini                    completed = True
1270c817347SPaolo Bonzini
128*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1290c817347SPaolo Bonzini        self.vm.shutdown()
1300c817347SPaolo Bonzini
1310c817347SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
1320c817347SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1330c817347SPaolo Bonzini                         'image file map does not match backing file after streaming')
1340c817347SPaolo Bonzini
1356e343609SPaolo Bonzini    def test_stream_partial(self):
136*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1376e343609SPaolo Bonzini
1386e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
1396e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1406e343609SPaolo Bonzini
1416e343609SPaolo Bonzini        completed = False
1426e343609SPaolo Bonzini        while not completed:
1436e343609SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1446e343609SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1456e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1466e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1476e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1486e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1496e343609SPaolo Bonzini                    completed = True
1506e343609SPaolo Bonzini
151*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1526e343609SPaolo Bonzini        self.vm.shutdown()
1536e343609SPaolo Bonzini
1546e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
1556e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1566e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1576e343609SPaolo Bonzini
15837ce63ebSStefan Hajnoczi    def test_device_not_found(self):
159db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
16037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
16137ce63ebSStefan Hajnoczi
162774a8850SStefan Hajnoczi
163774a8850SStefan Hajnocziclass TestSmallerBackingFile(ImageStreamingTestCase):
164774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
165774a8850SStefan Hajnoczi    image_len = 2 * backing_len
166774a8850SStefan Hajnoczi
167774a8850SStefan Hajnoczi    def setUp(self):
168774a8850SStefan Hajnoczi        self.create_image(backing_img, self.backing_len)
169774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
170774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
171774a8850SStefan Hajnoczi        self.vm.launch()
172774a8850SStefan Hajnoczi
173774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
174774a8850SStefan Hajnoczi    # end of the backing file is reached.
175774a8850SStefan Hajnoczi    def test_stream(self):
176*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
177774a8850SStefan Hajnoczi
178774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
179774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
180774a8850SStefan Hajnoczi
181774a8850SStefan Hajnoczi        completed = False
182774a8850SStefan Hajnoczi        while not completed:
183774a8850SStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
184774a8850SStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
185774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
186774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
187774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
188774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
189774a8850SStefan Hajnoczi                    completed = True
190774a8850SStefan Hajnoczi
191*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
192774a8850SStefan Hajnoczi        self.vm.shutdown()
193774a8850SStefan Hajnoczi
19490f0b711SPaolo Bonziniclass TestErrors(ImageStreamingTestCase):
19590f0b711SPaolo Bonzini    image_len = 2 * 1024 * 1024 # MB
19690f0b711SPaolo Bonzini
19790f0b711SPaolo Bonzini    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
19890f0b711SPaolo Bonzini    STREAM_BUFFER_SIZE = 512 * 1024
19990f0b711SPaolo Bonzini
20090f0b711SPaolo Bonzini    def create_blkdebug_file(self, name, event, errno):
20190f0b711SPaolo Bonzini        file = open(name, 'w')
20290f0b711SPaolo Bonzini        file.write('''
20390f0b711SPaolo Bonzini[inject-error]
20490f0b711SPaolo Bonzinistate = "1"
20590f0b711SPaolo Bonzinievent = "%s"
20690f0b711SPaolo Bonzinierrno = "%d"
20790f0b711SPaolo Bonziniimmediately = "off"
20890f0b711SPaolo Bonzinionce = "on"
20990f0b711SPaolo Bonzinisector = "%d"
21090f0b711SPaolo Bonzini
21190f0b711SPaolo Bonzini[set-state]
21290f0b711SPaolo Bonzinistate = "1"
21390f0b711SPaolo Bonzinievent = "%s"
21490f0b711SPaolo Bonzininew_state = "2"
21590f0b711SPaolo Bonzini
21690f0b711SPaolo Bonzini[set-state]
21790f0b711SPaolo Bonzinistate = "2"
21890f0b711SPaolo Bonzinievent = "%s"
21990f0b711SPaolo Bonzininew_state = "1"
22090f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
22190f0b711SPaolo Bonzini        file.close()
22290f0b711SPaolo Bonzini
22390f0b711SPaolo Bonziniclass TestEIO(TestErrors):
22490f0b711SPaolo Bonzini    def setUp(self):
22590f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
22690f0b711SPaolo Bonzini        self.create_image(backing_img, TestErrors.image_len)
22790f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
22890f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
22990f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
23090f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
23190f0b711SPaolo Bonzini                 test_img)
23290f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
23390f0b711SPaolo Bonzini        self.vm.launch()
23490f0b711SPaolo Bonzini
23590f0b711SPaolo Bonzini    def tearDown(self):
23690f0b711SPaolo Bonzini        self.vm.shutdown()
23790f0b711SPaolo Bonzini        os.remove(test_img)
23890f0b711SPaolo Bonzini        os.remove(backing_img)
23990f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
24090f0b711SPaolo Bonzini
24190f0b711SPaolo Bonzini    def test_report(self):
242*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
24390f0b711SPaolo Bonzini
24490f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
24590f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
24690f0b711SPaolo Bonzini
24790f0b711SPaolo Bonzini        completed = False
24890f0b711SPaolo Bonzini        error = False
24990f0b711SPaolo Bonzini        while not completed:
25090f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
25190f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
25290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
25390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
25490f0b711SPaolo Bonzini                    error = True
25590f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
25690f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
25790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
25890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
25990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
26090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
26190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
26290f0b711SPaolo Bonzini                    completed = True
26390f0b711SPaolo Bonzini
264*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
26590f0b711SPaolo Bonzini        self.vm.shutdown()
26690f0b711SPaolo Bonzini
26790f0b711SPaolo Bonzini    def test_ignore(self):
268*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
26990f0b711SPaolo Bonzini
27090f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
27190f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
27290f0b711SPaolo Bonzini
27390f0b711SPaolo Bonzini        error = False
27490f0b711SPaolo Bonzini        completed = False
27590f0b711SPaolo Bonzini        while not completed:
27690f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
27790f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
27890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
27990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
28090f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
28190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
28290f0b711SPaolo Bonzini                    error = True
28390f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
28490f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
28590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
28690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
28790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
28890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
28990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
29090f0b711SPaolo Bonzini                    completed = True
29190f0b711SPaolo Bonzini
292*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
29390f0b711SPaolo Bonzini        self.vm.shutdown()
29490f0b711SPaolo Bonzini
29590f0b711SPaolo Bonzini    def test_stop(self):
296*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
29790f0b711SPaolo Bonzini
29890f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
29990f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
30090f0b711SPaolo Bonzini
30190f0b711SPaolo Bonzini        error = False
30290f0b711SPaolo Bonzini        completed = False
30390f0b711SPaolo Bonzini        while not completed:
30490f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
30590f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
30690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
30790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
30890f0b711SPaolo Bonzini
30990f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
31090f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
31190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
31290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'failed')
31390f0b711SPaolo Bonzini
31490f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
31590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
31690f0b711SPaolo Bonzini
31790f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
31890f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
31990f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
32090f0b711SPaolo Bonzini                    error = True
32190f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
32290f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
32390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
32490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
32590f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
32690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
32790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
32890f0b711SPaolo Bonzini                    completed = True
32990f0b711SPaolo Bonzini
330*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
33190f0b711SPaolo Bonzini        self.vm.shutdown()
33290f0b711SPaolo Bonzini
33390f0b711SPaolo Bonzini    def test_enospc(self):
334*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
33590f0b711SPaolo Bonzini
33690f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
33790f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
33890f0b711SPaolo Bonzini
33990f0b711SPaolo Bonzini        completed = False
34090f0b711SPaolo Bonzini        error = False
34190f0b711SPaolo Bonzini        while not completed:
34290f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
34390f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
34490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
34590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
34690f0b711SPaolo Bonzini                    error = True
34790f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
34890f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
34990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
35090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
35190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
35290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
35390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
35490f0b711SPaolo Bonzini                    completed = True
35590f0b711SPaolo Bonzini
356*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
35790f0b711SPaolo Bonzini        self.vm.shutdown()
35890f0b711SPaolo Bonzini
35990f0b711SPaolo Bonziniclass TestENOSPC(TestErrors):
36090f0b711SPaolo Bonzini    def setUp(self):
36190f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
36290f0b711SPaolo Bonzini        self.create_image(backing_img, TestErrors.image_len)
36390f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
36490f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
36590f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
36690f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
36790f0b711SPaolo Bonzini                 test_img)
36890f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
36990f0b711SPaolo Bonzini        self.vm.launch()
37090f0b711SPaolo Bonzini
37190f0b711SPaolo Bonzini    def tearDown(self):
37290f0b711SPaolo Bonzini        self.vm.shutdown()
37390f0b711SPaolo Bonzini        os.remove(test_img)
37490f0b711SPaolo Bonzini        os.remove(backing_img)
37590f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
37690f0b711SPaolo Bonzini
37790f0b711SPaolo Bonzini    def test_enospc(self):
378*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
37990f0b711SPaolo Bonzini
38090f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
38190f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
38290f0b711SPaolo Bonzini
38390f0b711SPaolo Bonzini        error = False
38490f0b711SPaolo Bonzini        completed = False
38590f0b711SPaolo Bonzini        while not completed:
38690f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
38790f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
38890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
38990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
39090f0b711SPaolo Bonzini
39190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
39290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
39390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
39490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')
39590f0b711SPaolo Bonzini
39690f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
39790f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
39890f0b711SPaolo Bonzini
39990f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
40090f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
40190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
40290f0b711SPaolo Bonzini                    error = True
40390f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
40490f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
40590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
40690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
40790f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
40890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
40990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
41090f0b711SPaolo Bonzini                    completed = True
41190f0b711SPaolo Bonzini
412*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
41390f0b711SPaolo Bonzini        self.vm.shutdown()
414774a8850SStefan Hajnoczi
41537ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase):
41637ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
41737ce63ebSStefan Hajnoczi
41837ce63ebSStefan Hajnoczi    def setUp(self):
41937ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
42037ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
42137ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
42237ce63ebSStefan Hajnoczi        self.vm.launch()
42337ce63ebSStefan Hajnoczi
42437ce63ebSStefan Hajnoczi    def tearDown(self):
42537ce63ebSStefan Hajnoczi        self.vm.shutdown()
42637ce63ebSStefan Hajnoczi        os.remove(test_img)
42737ce63ebSStefan Hajnoczi        os.remove(backing_img)
42837ce63ebSStefan Hajnoczi
42937ce63ebSStefan Hajnoczi    def test_stream_stop(self):
430*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
43137ce63ebSStefan Hajnoczi
432db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
43337ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
43437ce63ebSStefan Hajnoczi
4350fd05e8dSPaolo Bonzini        time.sleep(0.1)
43637ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
43737ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
43837ce63ebSStefan Hajnoczi
439e425306aSStefan Hajnoczi        self.cancel_and_wait()
44037ce63ebSStefan Hajnoczi
44137ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase):
44237ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
44337ce63ebSStefan Hajnoczi
44437ce63ebSStefan Hajnoczi    def setUp(self):
44537ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
44637ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
44737ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
44837ce63ebSStefan Hajnoczi        self.vm.launch()
44937ce63ebSStefan Hajnoczi
45037ce63ebSStefan Hajnoczi    def tearDown(self):
45137ce63ebSStefan Hajnoczi        self.vm.shutdown()
45237ce63ebSStefan Hajnoczi        os.remove(test_img)
45337ce63ebSStefan Hajnoczi        os.remove(backing_img)
45437ce63ebSStefan Hajnoczi
455e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
456e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
457e425306aSStefan Hajnoczi    def perf_test_throughput(self):
458*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
45937ce63ebSStefan Hajnoczi
460db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
46137ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
46237ce63ebSStefan Hajnoczi
463e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
46437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
46537ce63ebSStefan Hajnoczi
46637ce63ebSStefan Hajnoczi        completed = False
46737ce63ebSStefan Hajnoczi        while not completed:
46837ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
46937ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
47037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
47137ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
47237ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
47337ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
47437ce63ebSStefan Hajnoczi                    completed = True
47537ce63ebSStefan Hajnoczi
476*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
47737ce63ebSStefan Hajnoczi
478e425306aSStefan Hajnoczi    def test_set_speed(self):
479*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
480e425306aSStefan Hajnoczi
481e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
482e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
483e425306aSStefan Hajnoczi
484e425306aSStefan Hajnoczi        # Default speed is 0
485e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
486e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
487e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
488e425306aSStefan Hajnoczi
489e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
490e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
491e425306aSStefan Hajnoczi
492e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
493e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
494e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
495e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
496e425306aSStefan Hajnoczi
497e425306aSStefan Hajnoczi        self.cancel_and_wait()
498e425306aSStefan Hajnoczi
499e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
500e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
501e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
502e425306aSStefan Hajnoczi
503e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
504e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
505e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
506e425306aSStefan Hajnoczi
507e425306aSStefan Hajnoczi        self.cancel_and_wait()
508e425306aSStefan Hajnoczi
509e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
510*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
511e425306aSStefan Hajnoczi
512e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
51358c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
514e425306aSStefan Hajnoczi
515*ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
516e425306aSStefan Hajnoczi
517e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
518e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
519e425306aSStefan Hajnoczi
520e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
52158c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
522e425306aSStefan Hajnoczi
523e425306aSStefan Hajnoczi        self.cancel_and_wait()
524e425306aSStefan Hajnoczi
52537ce63ebSStefan Hajnocziif __name__ == '__main__':
52637ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
527