xref: /qemu/tests/qemu-iotests/030 (revision 409d5498)
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
2537ce63ebSStefan Hajnoczi
2637ce63ebSStefan Hajnoczibacking_img = os.path.join(iotests.test_dir, 'backing.img')
276e343609SPaolo Bonzinimid_img = os.path.join(iotests.test_dir, 'mid.img')
2837ce63ebSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img')
2937ce63ebSStefan Hajnoczi
302499a096SStefan Hajnocziclass TestSingleDrive(iotests.QMPTestCase):
3137ce63ebSStefan Hajnoczi    image_len = 1 * 1024 * 1024 # MB
3237ce63ebSStefan Hajnoczi
3337ce63ebSStefan Hajnoczi    def setUp(self):
342499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestSingleDrive.image_len)
356e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
366e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
3790c9b167SKevin Wolf        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img)
385e302a7dSAlberto Garcia        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 524288 512', mid_img)
39b5e51dd7SFam Zheng        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
4037ce63ebSStefan Hajnoczi        self.vm.launch()
4137ce63ebSStefan Hajnoczi
4237ce63ebSStefan Hajnoczi    def tearDown(self):
4337ce63ebSStefan Hajnoczi        self.vm.shutdown()
4437ce63ebSStefan Hajnoczi        os.remove(test_img)
456e343609SPaolo Bonzini        os.remove(mid_img)
4637ce63ebSStefan Hajnoczi        os.remove(backing_img)
4737ce63ebSStefan Hajnoczi
4837ce63ebSStefan Hajnoczi    def test_stream(self):
49ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
5037ce63ebSStefan Hajnoczi
51db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
5237ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
5337ce63ebSStefan Hajnoczi
549974ad40SFam Zheng        self.wait_until_completed()
5537ce63ebSStefan Hajnoczi
56ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
57863a5d04SPaolo Bonzini        self.vm.shutdown()
5837ce63ebSStefan Hajnoczi
5990c9b167SKevin Wolf        self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
6090c9b167SKevin Wolf                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
61efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
6237ce63ebSStefan Hajnoczi
630c817347SPaolo Bonzini    def test_stream_pause(self):
64ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
650c817347SPaolo Bonzini
66b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
670c817347SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
680c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
690c817347SPaolo Bonzini
700c817347SPaolo Bonzini        result = self.vm.qmp('block-job-pause', device='drive0')
710c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
720c817347SPaolo Bonzini
730c817347SPaolo Bonzini        time.sleep(1)
740c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
750c817347SPaolo Bonzini        offset = self.dictpath(result, 'return[0]/offset')
760c817347SPaolo Bonzini
770c817347SPaolo Bonzini        time.sleep(1)
780c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
790c817347SPaolo Bonzini        self.assert_qmp(result, 'return[0]/offset', offset)
800c817347SPaolo Bonzini
810c817347SPaolo Bonzini        result = self.vm.qmp('block-job-resume', device='drive0')
820c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
830c817347SPaolo Bonzini
84b59b3d57SFam Zheng        self.vm.resume_drive('drive0')
859974ad40SFam Zheng        self.wait_until_completed()
860c817347SPaolo Bonzini
87ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
880c817347SPaolo Bonzini        self.vm.shutdown()
890c817347SPaolo Bonzini
9090c9b167SKevin Wolf        self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
9190c9b167SKevin Wolf                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
920c817347SPaolo Bonzini                         'image file map does not match backing file after streaming')
930c817347SPaolo Bonzini
94*409d5498SAlberto Garcia    def test_stream_no_op(self):
95*409d5498SAlberto Garcia        self.assert_no_active_block_jobs()
96*409d5498SAlberto Garcia
97*409d5498SAlberto Garcia        # The image map is empty before the operation
98*409d5498SAlberto Garcia        empty_map = qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img)
99*409d5498SAlberto Garcia
100*409d5498SAlberto Garcia        # This is a no-op: no data should ever be copied from the base image
101*409d5498SAlberto Garcia        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
102*409d5498SAlberto Garcia        self.assert_qmp(result, 'return', {})
103*409d5498SAlberto Garcia
104*409d5498SAlberto Garcia        self.wait_until_completed()
105*409d5498SAlberto Garcia
106*409d5498SAlberto Garcia        self.assert_no_active_block_jobs()
107*409d5498SAlberto Garcia        self.vm.shutdown()
108*409d5498SAlberto Garcia
109*409d5498SAlberto Garcia        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
110*409d5498SAlberto Garcia                         empty_map, 'image file map changed after a no-op')
111*409d5498SAlberto Garcia
1126e343609SPaolo Bonzini    def test_stream_partial(self):
113ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1146e343609SPaolo Bonzini
1155e302a7dSAlberto Garcia        result = self.vm.qmp('block-stream', device='drive0', base=backing_img)
1166e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1176e343609SPaolo Bonzini
1189974ad40SFam Zheng        self.wait_until_completed()
1196e343609SPaolo Bonzini
120ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1216e343609SPaolo Bonzini        self.vm.shutdown()
1226e343609SPaolo Bonzini
12390c9b167SKevin Wolf        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
12490c9b167SKevin Wolf                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
1256e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1266e343609SPaolo Bonzini
12737ce63ebSStefan Hajnoczi    def test_device_not_found(self):
128db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
12937ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
13037ce63ebSStefan Hajnoczi
131774a8850SStefan Hajnoczi
1322499a096SStefan Hajnocziclass TestSmallerBackingFile(iotests.QMPTestCase):
133774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
134774a8850SStefan Hajnoczi    image_len = 2 * backing_len
135774a8850SStefan Hajnoczi
136774a8850SStefan Hajnoczi    def setUp(self):
1372499a096SStefan Hajnoczi        iotests.create_image(backing_img, self.backing_len)
138774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
139774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
140774a8850SStefan Hajnoczi        self.vm.launch()
141774a8850SStefan Hajnoczi
142774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
143774a8850SStefan Hajnoczi    # end of the backing file is reached.
144774a8850SStefan Hajnoczi    def test_stream(self):
145ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
146774a8850SStefan Hajnoczi
147774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
148774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
149774a8850SStefan Hajnoczi
1509974ad40SFam Zheng        self.wait_until_completed()
151774a8850SStefan Hajnoczi
152ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
153774a8850SStefan Hajnoczi        self.vm.shutdown()
154774a8850SStefan Hajnoczi
1552499a096SStefan Hajnocziclass TestErrors(iotests.QMPTestCase):
15690f0b711SPaolo Bonzini    image_len = 2 * 1024 * 1024 # MB
15790f0b711SPaolo Bonzini
15890f0b711SPaolo Bonzini    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
15990f0b711SPaolo Bonzini    STREAM_BUFFER_SIZE = 512 * 1024
16090f0b711SPaolo Bonzini
16190f0b711SPaolo Bonzini    def create_blkdebug_file(self, name, event, errno):
16290f0b711SPaolo Bonzini        file = open(name, 'w')
16390f0b711SPaolo Bonzini        file.write('''
16490f0b711SPaolo Bonzini[inject-error]
16590f0b711SPaolo Bonzinistate = "1"
16690f0b711SPaolo Bonzinievent = "%s"
16790f0b711SPaolo Bonzinierrno = "%d"
16890f0b711SPaolo Bonziniimmediately = "off"
16990f0b711SPaolo Bonzinionce = "on"
17090f0b711SPaolo Bonzinisector = "%d"
17190f0b711SPaolo Bonzini
17290f0b711SPaolo Bonzini[set-state]
17390f0b711SPaolo Bonzinistate = "1"
17490f0b711SPaolo Bonzinievent = "%s"
17590f0b711SPaolo Bonzininew_state = "2"
17690f0b711SPaolo Bonzini
17790f0b711SPaolo Bonzini[set-state]
17890f0b711SPaolo Bonzinistate = "2"
17990f0b711SPaolo Bonzinievent = "%s"
18090f0b711SPaolo Bonzininew_state = "1"
18190f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
18290f0b711SPaolo Bonzini        file.close()
18390f0b711SPaolo Bonzini
18490f0b711SPaolo Bonziniclass TestEIO(TestErrors):
18590f0b711SPaolo Bonzini    def setUp(self):
18690f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
1872499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
18890f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
18990f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
19090f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
19190f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
19290f0b711SPaolo Bonzini                 test_img)
19390f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
19490f0b711SPaolo Bonzini        self.vm.launch()
19590f0b711SPaolo Bonzini
19690f0b711SPaolo Bonzini    def tearDown(self):
19790f0b711SPaolo Bonzini        self.vm.shutdown()
19890f0b711SPaolo Bonzini        os.remove(test_img)
19990f0b711SPaolo Bonzini        os.remove(backing_img)
20090f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
20190f0b711SPaolo Bonzini
20290f0b711SPaolo Bonzini    def test_report(self):
203ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
20490f0b711SPaolo Bonzini
20590f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
20690f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
20790f0b711SPaolo Bonzini
20890f0b711SPaolo Bonzini        completed = False
20990f0b711SPaolo Bonzini        error = False
21090f0b711SPaolo Bonzini        while not completed:
21190f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
21290f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
21390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
21490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
21590f0b711SPaolo Bonzini                    error = True
21690f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
21790f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
21890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
21990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
22090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
22190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
22290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
22390f0b711SPaolo Bonzini                    completed = True
22490f0b711SPaolo Bonzini
225ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
22690f0b711SPaolo Bonzini        self.vm.shutdown()
22790f0b711SPaolo Bonzini
22890f0b711SPaolo Bonzini    def test_ignore(self):
229ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
23090f0b711SPaolo Bonzini
23190f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
23290f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
23390f0b711SPaolo Bonzini
23490f0b711SPaolo Bonzini        error = False
23590f0b711SPaolo Bonzini        completed = False
23690f0b711SPaolo Bonzini        while not completed:
23790f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
23890f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
23990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
24090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
24190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
24290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
24390f0b711SPaolo Bonzini                    error = True
24490f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
24590f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
24690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
24790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
24890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
24990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
25090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
25190f0b711SPaolo Bonzini                    completed = True
25290f0b711SPaolo Bonzini
253ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
25490f0b711SPaolo Bonzini        self.vm.shutdown()
25590f0b711SPaolo Bonzini
25690f0b711SPaolo Bonzini    def test_stop(self):
257ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
25890f0b711SPaolo Bonzini
25990f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
26090f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
26190f0b711SPaolo Bonzini
26290f0b711SPaolo Bonzini        error = False
26390f0b711SPaolo Bonzini        completed = False
26490f0b711SPaolo Bonzini        while not completed:
26590f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
26690f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
26701809194SJohn Snow                    error = True
26890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
26990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
27090f0b711SPaolo Bonzini
27190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
27290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
27390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
27490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'failed')
27590f0b711SPaolo Bonzini
27690f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
27790f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
27890f0b711SPaolo Bonzini
27990f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
28001809194SJohn Snow                    if result == {'return': []}:
28101809194SJohn Snow                        # Race; likely already finished. Check.
28201809194SJohn Snow                        continue
28390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
28490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
28590f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
28690f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
28790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
28890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
28990f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
29090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
29190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
29290f0b711SPaolo Bonzini                    completed = True
29390f0b711SPaolo Bonzini
294ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
29590f0b711SPaolo Bonzini        self.vm.shutdown()
29690f0b711SPaolo Bonzini
29790f0b711SPaolo Bonzini    def test_enospc(self):
298ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
29990f0b711SPaolo Bonzini
30090f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
30190f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
30290f0b711SPaolo Bonzini
30390f0b711SPaolo Bonzini        completed = False
30490f0b711SPaolo Bonzini        error = False
30590f0b711SPaolo Bonzini        while not completed:
30690f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
30790f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
30890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
30990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
31090f0b711SPaolo Bonzini                    error = True
31190f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
31290f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
31390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
31490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
31590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
31690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
31790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
31890f0b711SPaolo Bonzini                    completed = True
31990f0b711SPaolo Bonzini
320ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
32190f0b711SPaolo Bonzini        self.vm.shutdown()
32290f0b711SPaolo Bonzini
32390f0b711SPaolo Bonziniclass TestENOSPC(TestErrors):
32490f0b711SPaolo Bonzini    def setUp(self):
32590f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
3262499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
32790f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
32890f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
32990f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
33090f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
33190f0b711SPaolo Bonzini                 test_img)
33290f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
33390f0b711SPaolo Bonzini        self.vm.launch()
33490f0b711SPaolo Bonzini
33590f0b711SPaolo Bonzini    def tearDown(self):
33690f0b711SPaolo Bonzini        self.vm.shutdown()
33790f0b711SPaolo Bonzini        os.remove(test_img)
33890f0b711SPaolo Bonzini        os.remove(backing_img)
33990f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
34090f0b711SPaolo Bonzini
34190f0b711SPaolo Bonzini    def test_enospc(self):
342ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
34390f0b711SPaolo Bonzini
34490f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
34590f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
34690f0b711SPaolo Bonzini
34790f0b711SPaolo Bonzini        error = False
34890f0b711SPaolo Bonzini        completed = False
34990f0b711SPaolo Bonzini        while not completed:
35090f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
35190f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
35290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
35390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
35490f0b711SPaolo Bonzini
35590f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
35690f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
35790f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
35890f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')
35990f0b711SPaolo Bonzini
36090f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
36190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
36290f0b711SPaolo Bonzini
36390f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
36490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
36590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
36690f0b711SPaolo Bonzini                    error = True
36790f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
36890f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
36990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
37090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
37190f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
37290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
37390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
37490f0b711SPaolo Bonzini                    completed = True
37590f0b711SPaolo Bonzini
376ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
37790f0b711SPaolo Bonzini        self.vm.shutdown()
378774a8850SStefan Hajnoczi
3792499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase):
38037ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
38137ce63ebSStefan Hajnoczi
38237ce63ebSStefan Hajnoczi    def setUp(self):
38337ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
38490c9b167SKevin Wolf        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img)
38537ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
38690c9b167SKevin Wolf        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img)
387b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
38837ce63ebSStefan Hajnoczi        self.vm.launch()
38937ce63ebSStefan Hajnoczi
39037ce63ebSStefan Hajnoczi    def tearDown(self):
39137ce63ebSStefan Hajnoczi        self.vm.shutdown()
39237ce63ebSStefan Hajnoczi        os.remove(test_img)
39337ce63ebSStefan Hajnoczi        os.remove(backing_img)
39437ce63ebSStefan Hajnoczi
39537ce63ebSStefan Hajnoczi    def test_stream_stop(self):
396ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
39737ce63ebSStefan Hajnoczi
398b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
399db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
40037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
40137ce63ebSStefan Hajnoczi
4020fd05e8dSPaolo Bonzini        time.sleep(0.1)
40337ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
40437ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
40537ce63ebSStefan Hajnoczi
406b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
40737ce63ebSStefan Hajnoczi
4082499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase):
40937ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
41037ce63ebSStefan Hajnoczi
41137ce63ebSStefan Hajnoczi    def setUp(self):
41237ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
41390c9b167SKevin Wolf        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img)
41437ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
41590c9b167SKevin Wolf        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img)
416b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
41737ce63ebSStefan Hajnoczi        self.vm.launch()
41837ce63ebSStefan Hajnoczi
41937ce63ebSStefan Hajnoczi    def tearDown(self):
42037ce63ebSStefan Hajnoczi        self.vm.shutdown()
42137ce63ebSStefan Hajnoczi        os.remove(test_img)
42237ce63ebSStefan Hajnoczi        os.remove(backing_img)
42337ce63ebSStefan Hajnoczi
424e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
425e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
426e425306aSStefan Hajnoczi    def perf_test_throughput(self):
427ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
42837ce63ebSStefan Hajnoczi
429db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
43037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
43137ce63ebSStefan Hajnoczi
432e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
43337ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
43437ce63ebSStefan Hajnoczi
4359974ad40SFam Zheng        self.wait_until_completed()
43637ce63ebSStefan Hajnoczi
437ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
43837ce63ebSStefan Hajnoczi
439e425306aSStefan Hajnoczi    def test_set_speed(self):
440ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
441e425306aSStefan Hajnoczi
442b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
443e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
444e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
445e425306aSStefan Hajnoczi
446e425306aSStefan Hajnoczi        # Default speed is 0
447e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
448e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
449e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
450e425306aSStefan Hajnoczi
451e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
452e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
453e425306aSStefan Hajnoczi
454e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
455e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
456e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
457e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
458e425306aSStefan Hajnoczi
459b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
460b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
461e425306aSStefan Hajnoczi
462e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
463e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
464e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
465e425306aSStefan Hajnoczi
466e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
467e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
468e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
469e425306aSStefan Hajnoczi
470b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
471e425306aSStefan Hajnoczi
472e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
473ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
474e425306aSStefan Hajnoczi
475e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
47658c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
477e425306aSStefan Hajnoczi
478ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
479e425306aSStefan Hajnoczi
480e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
481e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
482e425306aSStefan Hajnoczi
483e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
48458c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
485e425306aSStefan Hajnoczi
486e425306aSStefan Hajnoczi        self.cancel_and_wait()
487e425306aSStefan Hajnoczi
48837ce63ebSStefan Hajnocziif __name__ == '__main__':
48937ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
490