xref: /openbmc/qemu/tests/qemu-iotests/030 (revision b59b3d57737a0d40450f8232abd89e8986387402)
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)
37*b59b3d57SFam 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
5337ce63ebSStefan Hajnoczi        completed = False
5437ce63ebSStefan Hajnoczi        while not completed:
5537ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
5637ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
5737ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
5837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
5937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
6037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
6137ce63ebSStefan Hajnoczi                    completed = True
6237ce63ebSStefan Hajnoczi
63ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
64863a5d04SPaolo Bonzini        self.vm.shutdown()
6537ce63ebSStefan Hajnoczi
66efcc7a23SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
67efcc7a23SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
68efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
6937ce63ebSStefan Hajnoczi
700c817347SPaolo Bonzini    def test_stream_pause(self):
71ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
720c817347SPaolo Bonzini
73*b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
740c817347SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
750c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
760c817347SPaolo Bonzini
770c817347SPaolo Bonzini        result = self.vm.qmp('block-job-pause', device='drive0')
780c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
790c817347SPaolo Bonzini
800c817347SPaolo Bonzini        time.sleep(1)
810c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
820c817347SPaolo Bonzini        offset = self.dictpath(result, 'return[0]/offset')
830c817347SPaolo Bonzini
840c817347SPaolo Bonzini        time.sleep(1)
850c817347SPaolo Bonzini        result = self.vm.qmp('query-block-jobs')
860c817347SPaolo Bonzini        self.assert_qmp(result, 'return[0]/offset', offset)
870c817347SPaolo Bonzini
880c817347SPaolo Bonzini        result = self.vm.qmp('block-job-resume', device='drive0')
890c817347SPaolo Bonzini        self.assert_qmp(result, 'return', {})
900c817347SPaolo Bonzini
91*b59b3d57SFam Zheng        self.vm.resume_drive('drive0')
920c817347SPaolo Bonzini        completed = False
930c817347SPaolo Bonzini        while not completed:
940c817347SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
950c817347SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
960c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
970c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
980c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
990c817347SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1000c817347SPaolo Bonzini                    completed = True
1010c817347SPaolo Bonzini
102ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1030c817347SPaolo Bonzini        self.vm.shutdown()
1040c817347SPaolo Bonzini
1050c817347SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
1060c817347SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1070c817347SPaolo Bonzini                         'image file map does not match backing file after streaming')
1080c817347SPaolo Bonzini
1096e343609SPaolo Bonzini    def test_stream_partial(self):
110ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1116e343609SPaolo Bonzini
1126e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
1136e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1146e343609SPaolo Bonzini
1156e343609SPaolo Bonzini        completed = False
1166e343609SPaolo Bonzini        while not completed:
1176e343609SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1186e343609SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1196e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1206e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1216e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1226e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1236e343609SPaolo Bonzini                    completed = True
1246e343609SPaolo Bonzini
125ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
1266e343609SPaolo Bonzini        self.vm.shutdown()
1276e343609SPaolo Bonzini
1286e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
1296e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1306e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1316e343609SPaolo Bonzini
13237ce63ebSStefan Hajnoczi    def test_device_not_found(self):
133db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
13437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
13537ce63ebSStefan Hajnoczi
136774a8850SStefan Hajnoczi
1372499a096SStefan Hajnocziclass TestSmallerBackingFile(iotests.QMPTestCase):
138774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
139774a8850SStefan Hajnoczi    image_len = 2 * backing_len
140774a8850SStefan Hajnoczi
141774a8850SStefan Hajnoczi    def setUp(self):
1422499a096SStefan Hajnoczi        iotests.create_image(backing_img, self.backing_len)
143774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
144774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
145774a8850SStefan Hajnoczi        self.vm.launch()
146774a8850SStefan Hajnoczi
147774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
148774a8850SStefan Hajnoczi    # end of the backing file is reached.
149774a8850SStefan Hajnoczi    def test_stream(self):
150ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
151774a8850SStefan Hajnoczi
152774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
153774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
154774a8850SStefan Hajnoczi
155774a8850SStefan Hajnoczi        completed = False
156774a8850SStefan Hajnoczi        while not completed:
157774a8850SStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
158774a8850SStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
159774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
160774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
161774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
162774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
163774a8850SStefan Hajnoczi                    completed = True
164774a8850SStefan Hajnoczi
165ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
166774a8850SStefan Hajnoczi        self.vm.shutdown()
167774a8850SStefan Hajnoczi
1682499a096SStefan Hajnocziclass TestErrors(iotests.QMPTestCase):
16990f0b711SPaolo Bonzini    image_len = 2 * 1024 * 1024 # MB
17090f0b711SPaolo Bonzini
17190f0b711SPaolo Bonzini    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
17290f0b711SPaolo Bonzini    STREAM_BUFFER_SIZE = 512 * 1024
17390f0b711SPaolo Bonzini
17490f0b711SPaolo Bonzini    def create_blkdebug_file(self, name, event, errno):
17590f0b711SPaolo Bonzini        file = open(name, 'w')
17690f0b711SPaolo Bonzini        file.write('''
17790f0b711SPaolo Bonzini[inject-error]
17890f0b711SPaolo Bonzinistate = "1"
17990f0b711SPaolo Bonzinievent = "%s"
18090f0b711SPaolo Bonzinierrno = "%d"
18190f0b711SPaolo Bonziniimmediately = "off"
18290f0b711SPaolo Bonzinionce = "on"
18390f0b711SPaolo Bonzinisector = "%d"
18490f0b711SPaolo Bonzini
18590f0b711SPaolo Bonzini[set-state]
18690f0b711SPaolo Bonzinistate = "1"
18790f0b711SPaolo Bonzinievent = "%s"
18890f0b711SPaolo Bonzininew_state = "2"
18990f0b711SPaolo Bonzini
19090f0b711SPaolo Bonzini[set-state]
19190f0b711SPaolo Bonzinistate = "2"
19290f0b711SPaolo Bonzinievent = "%s"
19390f0b711SPaolo Bonzininew_state = "1"
19490f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
19590f0b711SPaolo Bonzini        file.close()
19690f0b711SPaolo Bonzini
19790f0b711SPaolo Bonziniclass TestEIO(TestErrors):
19890f0b711SPaolo Bonzini    def setUp(self):
19990f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
2002499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
20190f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
20290f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
20390f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
20490f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
20590f0b711SPaolo Bonzini                 test_img)
20690f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
20790f0b711SPaolo Bonzini        self.vm.launch()
20890f0b711SPaolo Bonzini
20990f0b711SPaolo Bonzini    def tearDown(self):
21090f0b711SPaolo Bonzini        self.vm.shutdown()
21190f0b711SPaolo Bonzini        os.remove(test_img)
21290f0b711SPaolo Bonzini        os.remove(backing_img)
21390f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
21490f0b711SPaolo Bonzini
21590f0b711SPaolo Bonzini    def test_report(self):
216ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
21790f0b711SPaolo Bonzini
21890f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0')
21990f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
22090f0b711SPaolo Bonzini
22190f0b711SPaolo Bonzini        completed = False
22290f0b711SPaolo Bonzini        error = False
22390f0b711SPaolo Bonzini        while not completed:
22490f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
22590f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
22690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
22790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
22890f0b711SPaolo Bonzini                    error = True
22990f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
23090f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
23190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
23290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
23390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
23490f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
23590f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
23690f0b711SPaolo Bonzini                    completed = True
23790f0b711SPaolo Bonzini
238ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
23990f0b711SPaolo Bonzini        self.vm.shutdown()
24090f0b711SPaolo Bonzini
24190f0b711SPaolo Bonzini    def test_ignore(self):
242ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
24390f0b711SPaolo Bonzini
24490f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
24590f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
24690f0b711SPaolo Bonzini
24790f0b711SPaolo Bonzini        error = False
24890f0b711SPaolo Bonzini        completed = 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                    result = self.vm.qmp('query-block-jobs')
25590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
25690f0b711SPaolo Bonzini                    error = True
25790f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
25890f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
25990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
26090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
26190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/error', 'Input/output error')
26290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
26390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
26490f0b711SPaolo Bonzini                    completed = True
26590f0b711SPaolo Bonzini
266ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
26790f0b711SPaolo Bonzini        self.vm.shutdown()
26890f0b711SPaolo Bonzini
26990f0b711SPaolo Bonzini    def test_stop(self):
270ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
27190f0b711SPaolo Bonzini
27290f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
27390f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
27490f0b711SPaolo Bonzini
27590f0b711SPaolo Bonzini        error = False
27690f0b711SPaolo Bonzini        completed = False
27790f0b711SPaolo Bonzini        while not completed:
27890f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
27990f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
28090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
28190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
28290f0b711SPaolo Bonzini
28390f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
28490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
28590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
28690f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'failed')
28790f0b711SPaolo Bonzini
28890f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
28990f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
29090f0b711SPaolo Bonzini
29190f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
29290f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
29390f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
29490f0b711SPaolo Bonzini                    error = True
29590f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
29690f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
29790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
29890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
29990f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
30090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
30190f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
30290f0b711SPaolo Bonzini                    completed = True
30390f0b711SPaolo Bonzini
304ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
30590f0b711SPaolo Bonzini        self.vm.shutdown()
30690f0b711SPaolo Bonzini
30790f0b711SPaolo Bonzini    def test_enospc(self):
308ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
30990f0b711SPaolo Bonzini
31090f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
31190f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
31290f0b711SPaolo Bonzini
31390f0b711SPaolo Bonzini        completed = False
31490f0b711SPaolo Bonzini        error = False
31590f0b711SPaolo Bonzini        while not completed:
31690f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
31790f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
31890f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
31990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
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(event, 'data/error', 'Input/output error')
32690f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
32790f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
32890f0b711SPaolo Bonzini                    completed = True
32990f0b711SPaolo Bonzini
330ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
33190f0b711SPaolo Bonzini        self.vm.shutdown()
33290f0b711SPaolo Bonzini
33390f0b711SPaolo Bonziniclass TestENOSPC(TestErrors):
33490f0b711SPaolo Bonzini    def setUp(self):
33590f0b711SPaolo Bonzini        self.blkdebug_file = backing_img + ".blkdebug"
3362499a096SStefan Hajnoczi        iotests.create_image(backing_img, TestErrors.image_len)
33790f0b711SPaolo Bonzini        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
33890f0b711SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt,
33990f0b711SPaolo Bonzini                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
34090f0b711SPaolo Bonzini                       % (self.blkdebug_file, backing_img),
34190f0b711SPaolo Bonzini                 test_img)
34290f0b711SPaolo Bonzini        self.vm = iotests.VM().add_drive(test_img)
34390f0b711SPaolo Bonzini        self.vm.launch()
34490f0b711SPaolo Bonzini
34590f0b711SPaolo Bonzini    def tearDown(self):
34690f0b711SPaolo Bonzini        self.vm.shutdown()
34790f0b711SPaolo Bonzini        os.remove(test_img)
34890f0b711SPaolo Bonzini        os.remove(backing_img)
34990f0b711SPaolo Bonzini        os.remove(self.blkdebug_file)
35090f0b711SPaolo Bonzini
35190f0b711SPaolo Bonzini    def test_enospc(self):
352ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
35390f0b711SPaolo Bonzini
35490f0b711SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
35590f0b711SPaolo Bonzini        self.assert_qmp(result, 'return', {})
35690f0b711SPaolo Bonzini
35790f0b711SPaolo Bonzini        error = False
35890f0b711SPaolo Bonzini        completed = False
35990f0b711SPaolo Bonzini        while not completed:
36090f0b711SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
36190f0b711SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_ERROR':
36290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
36390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/operation', 'read')
36490f0b711SPaolo Bonzini
36590f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
36690f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', True)
36790f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
36890f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')
36990f0b711SPaolo Bonzini
37090f0b711SPaolo Bonzini                    result = self.vm.qmp('block-job-resume', device='drive0')
37190f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return', {})
37290f0b711SPaolo Bonzini
37390f0b711SPaolo Bonzini                    result = self.vm.qmp('query-block-jobs')
37490f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/paused', False)
37590f0b711SPaolo Bonzini                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
37690f0b711SPaolo Bonzini                    error = True
37790f0b711SPaolo Bonzini                elif event['event'] == 'BLOCK_JOB_COMPLETED':
37890f0b711SPaolo Bonzini                    self.assertTrue(error, 'job completed unexpectedly')
37990f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
38090f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
38190f0b711SPaolo Bonzini                    self.assert_qmp_absent(event, 'data/error')
38290f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
38390f0b711SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
38490f0b711SPaolo Bonzini                    completed = True
38590f0b711SPaolo Bonzini
386ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
38790f0b711SPaolo Bonzini        self.vm.shutdown()
388774a8850SStefan Hajnoczi
3892499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase):
39037ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
39137ce63ebSStefan Hajnoczi
39237ce63ebSStefan Hajnoczi    def setUp(self):
39337ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
3947890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
39537ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
3967890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
397*b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
39837ce63ebSStefan Hajnoczi        self.vm.launch()
39937ce63ebSStefan Hajnoczi
40037ce63ebSStefan Hajnoczi    def tearDown(self):
40137ce63ebSStefan Hajnoczi        self.vm.shutdown()
40237ce63ebSStefan Hajnoczi        os.remove(test_img)
40337ce63ebSStefan Hajnoczi        os.remove(backing_img)
40437ce63ebSStefan Hajnoczi
40537ce63ebSStefan Hajnoczi    def test_stream_stop(self):
406ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
40737ce63ebSStefan Hajnoczi
408*b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
409db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
41037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
41137ce63ebSStefan Hajnoczi
4120fd05e8dSPaolo Bonzini        time.sleep(0.1)
41337ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
41437ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
41537ce63ebSStefan Hajnoczi
416*b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
41737ce63ebSStefan Hajnoczi
4182499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase):
41937ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
42037ce63ebSStefan Hajnoczi
42137ce63ebSStefan Hajnoczi    def setUp(self):
42237ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
4237890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
42437ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
4257890111bSFam Zheng        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
426*b59b3d57SFam Zheng        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
42737ce63ebSStefan Hajnoczi        self.vm.launch()
42837ce63ebSStefan Hajnoczi
42937ce63ebSStefan Hajnoczi    def tearDown(self):
43037ce63ebSStefan Hajnoczi        self.vm.shutdown()
43137ce63ebSStefan Hajnoczi        os.remove(test_img)
43237ce63ebSStefan Hajnoczi        os.remove(backing_img)
43337ce63ebSStefan Hajnoczi
434e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
435e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
436e425306aSStefan Hajnoczi    def perf_test_throughput(self):
437ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
43837ce63ebSStefan Hajnoczi
439db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
44037ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
44137ce63ebSStefan Hajnoczi
442e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
44337ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
44437ce63ebSStefan Hajnoczi
44537ce63ebSStefan Hajnoczi        completed = False
44637ce63ebSStefan Hajnoczi        while not completed:
44737ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
44837ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
44937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
45037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
45137ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
45237ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
45337ce63ebSStefan Hajnoczi                    completed = True
45437ce63ebSStefan Hajnoczi
455ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
45637ce63ebSStefan Hajnoczi
457e425306aSStefan Hajnoczi    def test_set_speed(self):
458ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
459e425306aSStefan Hajnoczi
460*b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
461e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
462e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
463e425306aSStefan Hajnoczi
464e425306aSStefan Hajnoczi        # Default speed is 0
465e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
466e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
467e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
468e425306aSStefan Hajnoczi
469e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
470e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
471e425306aSStefan Hajnoczi
472e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
473e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
474e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
475e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
476e425306aSStefan Hajnoczi
477*b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
478*b59b3d57SFam Zheng        self.vm.pause_drive('drive0')
479e425306aSStefan Hajnoczi
480e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
481e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
482e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
483e425306aSStefan Hajnoczi
484e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
485e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
486e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
487e425306aSStefan Hajnoczi
488*b59b3d57SFam Zheng        self.cancel_and_wait(resume=True)
489e425306aSStefan Hajnoczi
490e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
491ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
492e425306aSStefan Hajnoczi
493e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
49458c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
495e425306aSStefan Hajnoczi
496ecc1c88eSStefan Hajnoczi        self.assert_no_active_block_jobs()
497e425306aSStefan Hajnoczi
498e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
499e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
500e425306aSStefan Hajnoczi
501e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
50258c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
503e425306aSStefan Hajnoczi
504e425306aSStefan Hajnoczi        self.cancel_and_wait()
505e425306aSStefan Hajnoczi
50637ce63ebSStefan Hajnocziif __name__ == '__main__':
50737ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
508