xref: /qemu/tests/qemu-iotests/030 (revision 9974ad40)
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)
37b59b3d57SFam Zheng        qemu_io('-c', 'write -P 0x1 0 512', backing_img)
3837ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
3937ce63ebSStefan Hajnoczi        self.vm.launch()
4037ce63ebSStefan Hajnoczi
4137ce63ebSStefan Hajnoczi    def tearDown(self):
4237ce63ebSStefan Hajnoczi        self.vm.shutdown()
4337ce63ebSStefan Hajnoczi        os.remove(test_img)
446e343609SPaolo Bonzini        os.remove(mid_img)
4537ce63ebSStefan Hajnoczi        os.remove(backing_img)
4637ce63ebSStefan Hajnoczi
4737ce63ebSStefan Hajnoczi    def test_stream(self):
48ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
4937ce63ebSStefan Hajnoczi
50db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
5137ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
5237ce63ebSStefan Hajnoczi
53*9974ad40SFam Zheng        self.wait_until_completed()
5437ce63ebSStefan Hajnoczi
55ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
56863a5d04SPaolo Bonzini        self.vm.shutdown()
5737ce63ebSStefan Hajnoczi
58efcc7a23SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
59efcc7a23SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
60efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
6137ce63ebSStefan Hajnoczi
620c817347SPaolo Bonzini    def test_stream_pause(self):
63ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
640c817347SPaolo Bonzini
65b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
660c817347SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
670c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
680c817347SPaolo Bonzini
690c817347SPaolo Bonzini        result = self.vm.qmp('block-job-pause', device='drive0')
700c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
710c817347SPaolo Bonzini
720c817347SPaolo Bonzini        time.sleep(1)
730c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
740c817347SPaolo Bonzini        offset = self.dictpath(result, 'return[0]/offset')
750c817347SPaolo Bonzini
760c817347SPaolo Bonzini        time.sleep(1)
770c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
780c817347SPaolo Bonzini        self.assert_qmp(result, 'return[0]/offset', offset)
790c817347SPaolo Bonzini
800c817347SPaolo Bonzini        result = self.vm.qmp('block-job-resume', device='drive0')
810c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
820c817347SPaolo Bonzini
83b59b3d57SFam Zheng        self.vm.resume_drive('drive0')
84*9974ad40SFam Zheng        self.wait_until_completed()
850c817347SPaolo Bonzini
86ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
870c817347SPaolo Bonzini        self.vm.shutdown()
880c817347SPaolo Bonzini
890c817347SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
900c817347SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
910c817347SPaolo Bonzini                         'image file map does not match backing file after streaming')
920c817347SPaolo Bonzini
936e343609SPaolo Bonzini    def test_stream_partial(self):
94ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
956e343609SPaolo Bonzini
966e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
976e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
986e343609SPaolo Bonzini
99*9974ad40SFam Zheng        self.wait_until_completed()
1006e343609SPaolo Bonzini
101ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1026e343609SPaolo Bonzini        self.vm.shutdown()
1036e343609SPaolo Bonzini
1046e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
1056e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1066e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1076e343609SPaolo Bonzini
10837ce63ebSStefan Hajnoczi    def test_device_not_found(self):
109db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
11037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
11137ce63ebSStefan Hajnoczi
112774a8850SStefan Hajnoczi
1132499a096SStefan Hajnocziclass TestSmallerBackingFile(iotests.QMPTestCase):
114774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
115774a8850SStefan Hajnoczi    image_len = 2 * backing_len
116774a8850SStefan Hajnoczi
117774a8850SStefan Hajnoczi    def setUp(self):
1182499a096SStefan Hajnoczi        iotests.create_image(backing_img, self.backing_len)
119774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
120774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
121774a8850SStefan Hajnoczi        self.vm.launch()
122774a8850SStefan Hajnoczi
123774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
124774a8850SStefan Hajnoczi    # end of the backing file is reached.
125774a8850SStefan Hajnoczi    def test_stream(self):
126ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
127774a8850SStefan Hajnoczi
128774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
129774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
130774a8850SStefan Hajnoczi
131*9974ad40SFam Zheng        self.wait_until_completed()
132774a8850SStefan Hajnoczi
133ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
134774a8850SStefan Hajnoczi        self.vm.shutdown()
135774a8850SStefan Hajnoczi
1362499a096SStefan Hajnocziclass TestErrors(iotests.QMPTestCase):
13790f0b711SPaolo Bonzini    image_len = 2 * 1024 * 1024 # MB
13890f0b711SPaolo Bonzini
13990f0b711SPaolo Bonzini    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
14090f0b711SPaolo Bonzini    STREAM_BUFFER_SIZE = 512 * 1024
14190f0b711SPaolo Bonzini
14290f0b711SPaolo Bonzini    def create_blkdebug_file(self, name, event, errno):
14390f0b711SPaolo Bonzini        file = open(name, 'w')
14490f0b711SPaolo Bonzini        file.write('''
14590f0b711SPaolo Bonzini[inject-error]
14690f0b711SPaolo Bonzinistate = "1"
14790f0b711SPaolo Bonzinievent = "%s"
14890f0b711SPaolo Bonzinierrno = "%d"
14990f0b711SPaolo Bonziniimmediately = "off"
15090f0b711SPaolo Bonzinionce = "on"
15190f0b711SPaolo Bonzinisector = "%d"
15290f0b711SPaolo Bonzini
15390f0b711SPaolo Bonzini[set-state]
15490f0b711SPaolo Bonzinistate = "1"
15590f0b711SPaolo Bonzinievent = "%s"
15690f0b711SPaolo Bonzininew_state = "2"
15790f0b711SPaolo Bonzini
15890f0b711SPaolo Bonzini[set-state]
15990f0b711SPaolo Bonzinistate = "2"
16090f0b711SPaolo Bonzinievent = "%s"
16190f0b711SPaolo Bonzininew_state = "1"
16290f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
16390f0b711SPaolo Bonzini        file.close()
16490f0b711SPaolo Bonzini
16590f0b711SPaolo Bonziniclass TestEIO(TestErrors):
16690f0b711SPaolo Bonzini    def setUp(self):
16790f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
1682499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
16990f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
17090f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
17190f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
17290f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
17390f0b711SPaolo Bonzini                 test_img)
17490f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
17590f0b711SPaolo Bonzini        self.vm.launch()
17690f0b711SPaolo Bonzini
17790f0b711SPaolo Bonzini    def tearDown(self):
17890f0b711SPaolo Bonzini        self.vm.shutdown()
17990f0b711SPaolo Bonzini        os.remove(test_img)
18090f0b711SPaolo Bonzini        os.remove(backing_img)
18190f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
18290f0b711SPaolo Bonzini
18390f0b711SPaolo Bonzini    def test_report(self):
184ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
18590f0b711SPaolo Bonzini
18690f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
18790f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
18890f0b711SPaolo Bonzini
18990f0b711SPaolo Bonzini        completed = False
19090f0b711SPaolo Bonzini        error = False
19190f0b711SPaolo Bonzini        while not completed:
19290f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
19390f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
19490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
19590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
19690f0b711SPaolo Bonzini                    error = True
19790f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
19890f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
19990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
20090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
20190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
20290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
20390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
20490f0b711SPaolo Bonzini                    completed = True
20590f0b711SPaolo Bonzini
206ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
20790f0b711SPaolo Bonzini        self.vm.shutdown()
20890f0b711SPaolo Bonzini
20990f0b711SPaolo Bonzini    def test_ignore(self):
210ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
21190f0b711SPaolo Bonzini
21290f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
21390f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
21490f0b711SPaolo Bonzini
21590f0b711SPaolo Bonzini        error = False
21690f0b711SPaolo Bonzini        completed = False
21790f0b711SPaolo Bonzini        while not completed:
21890f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
21990f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
22090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
22190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
22290f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
22390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
22490f0b711SPaolo Bonzini                    error = True
22590f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
22690f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
22790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
22890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
22990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
23090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
23190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
23290f0b711SPaolo Bonzini                    completed = True
23390f0b711SPaolo Bonzini
234ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
23590f0b711SPaolo Bonzini        self.vm.shutdown()
23690f0b711SPaolo Bonzini
23790f0b711SPaolo Bonzini    def test_stop(self):
238ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
23990f0b711SPaolo Bonzini
24090f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
24190f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
24290f0b711SPaolo Bonzini
24390f0b711SPaolo Bonzini        error = False
24490f0b711SPaolo Bonzini        completed = False
24590f0b711SPaolo Bonzini        while not completed:
24690f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
24790f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
24890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
24990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
25090f0b711SPaolo Bonzini
25190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
25290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
25390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
25490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'failed')
25590f0b711SPaolo Bonzini
25690f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
25790f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
25890f0b711SPaolo Bonzini
25990f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
26090f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
26190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
26290f0b711SPaolo Bonzini                    error = True
26390f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
26490f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
26590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
26690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
26790f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
26890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
26990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
27090f0b711SPaolo Bonzini                    completed = True
27190f0b711SPaolo Bonzini
272ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
27390f0b711SPaolo Bonzini        self.vm.shutdown()
27490f0b711SPaolo Bonzini
27590f0b711SPaolo Bonzini    def test_enospc(self):
276ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
27790f0b711SPaolo Bonzini
27890f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
27990f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
28090f0b711SPaolo Bonzini
28190f0b711SPaolo Bonzini        completed = False
28290f0b711SPaolo Bonzini        error = False
28390f0b711SPaolo Bonzini        while not completed:
28490f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
28590f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
28690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
28790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
28890f0b711SPaolo Bonzini                    error = True
28990f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
29090f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
29190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
29290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
29390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
29490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
29590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
29690f0b711SPaolo Bonzini                    completed = True
29790f0b711SPaolo Bonzini
298ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
29990f0b711SPaolo Bonzini        self.vm.shutdown()
30090f0b711SPaolo Bonzini
30190f0b711SPaolo Bonziniclass TestENOSPC(TestErrors):
30290f0b711SPaolo Bonzini    def setUp(self):
30390f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
3042499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
30590f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
30690f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
30790f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
30890f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
30990f0b711SPaolo Bonzini                 test_img)
31090f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
31190f0b711SPaolo Bonzini        self.vm.launch()
31290f0b711SPaolo Bonzini
31390f0b711SPaolo Bonzini    def tearDown(self):
31490f0b711SPaolo Bonzini        self.vm.shutdown()
31590f0b711SPaolo Bonzini        os.remove(test_img)
31690f0b711SPaolo Bonzini        os.remove(backing_img)
31790f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
31890f0b711SPaolo Bonzini
31990f0b711SPaolo Bonzini    def test_enospc(self):
320ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
32190f0b711SPaolo Bonzini
32290f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
32390f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
32490f0b711SPaolo Bonzini
32590f0b711SPaolo Bonzini        error = False
32690f0b711SPaolo Bonzini        completed = False
32790f0b711SPaolo Bonzini        while not completed:
32890f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
32990f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
33090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
33190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
33290f0b711SPaolo Bonzini
33390f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
33490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
33590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
33690f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')
33790f0b711SPaolo Bonzini
33890f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
33990f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
34090f0b711SPaolo Bonzini
34190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
34290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
34390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
34490f0b711SPaolo Bonzini                    error = True
34590f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
34690f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
34790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
34890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
34990f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
35090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
35190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
35290f0b711SPaolo Bonzini                    completed = True
35390f0b711SPaolo Bonzini
354ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
35590f0b711SPaolo Bonzini        self.vm.shutdown()
356774a8850SStefan Hajnoczi
3572499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase):
35837ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
35937ce63ebSStefan Hajnoczi
36037ce63ebSStefan Hajnoczi    def setUp(self):
36137ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
3627890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
36337ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
3647890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
365b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
36637ce63ebSStefan Hajnoczi        self.vm.launch()
36737ce63ebSStefan Hajnoczi
36837ce63ebSStefan Hajnoczi    def tearDown(self):
36937ce63ebSStefan Hajnoczi        self.vm.shutdown()
37037ce63ebSStefan Hajnoczi        os.remove(test_img)
37137ce63ebSStefan Hajnoczi        os.remove(backing_img)
37237ce63ebSStefan Hajnoczi
37337ce63ebSStefan Hajnoczi    def test_stream_stop(self):
374ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
37537ce63ebSStefan Hajnoczi
376b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
377db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
37837ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
37937ce63ebSStefan Hajnoczi
3800fd05e8dSPaolo Bonzini        time.sleep(0.1)
38137ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
38237ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
38337ce63ebSStefan Hajnoczi
384b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
38537ce63ebSStefan Hajnoczi
3862499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase):
38737ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
38837ce63ebSStefan Hajnoczi
38937ce63ebSStefan Hajnoczi    def setUp(self):
39037ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
3917890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
39237ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
3937890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
394b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
39537ce63ebSStefan Hajnoczi        self.vm.launch()
39637ce63ebSStefan Hajnoczi
39737ce63ebSStefan Hajnoczi    def tearDown(self):
39837ce63ebSStefan Hajnoczi        self.vm.shutdown()
39937ce63ebSStefan Hajnoczi        os.remove(test_img)
40037ce63ebSStefan Hajnoczi        os.remove(backing_img)
40137ce63ebSStefan Hajnoczi
402e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
403e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
404e425306aSStefan Hajnoczi    def perf_test_throughput(self):
405ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
40637ce63ebSStefan Hajnoczi
407db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
40837ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
40937ce63ebSStefan Hajnoczi
410e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
41137ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
41237ce63ebSStefan Hajnoczi
413*9974ad40SFam Zheng        self.wait_until_completed()
41437ce63ebSStefan Hajnoczi
415ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
41637ce63ebSStefan Hajnoczi
417e425306aSStefan Hajnoczi    def test_set_speed(self):
418ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
419e425306aSStefan Hajnoczi
420b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
421e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
422e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
423e425306aSStefan Hajnoczi
424e425306aSStefan Hajnoczi        # Default speed is 0
425e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
426e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
427e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
428e425306aSStefan Hajnoczi
429e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
430e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
431e425306aSStefan Hajnoczi
432e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
433e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
434e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
435e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
436e425306aSStefan Hajnoczi
437b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
438b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
439e425306aSStefan Hajnoczi
440e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
441e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
442e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
443e425306aSStefan Hajnoczi
444e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
445e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
446e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
447e425306aSStefan Hajnoczi
448b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
449e425306aSStefan Hajnoczi
450e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
451ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
452e425306aSStefan Hajnoczi
453e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
45458c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
455e425306aSStefan Hajnoczi
456ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
457e425306aSStefan Hajnoczi
458e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
459e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
460e425306aSStefan Hajnoczi
461e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
46258c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
463e425306aSStefan Hajnoczi
464e425306aSStefan Hajnoczi        self.cancel_and_wait()
465e425306aSStefan Hajnoczi
46637ce63ebSStefan Hajnocziif __name__ == '__main__':
46737ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
468