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) 38*5e302a7dSAlberto 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 946e343609SPaolo Bonzini def test_stream_partial(self): 95ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 966e343609SPaolo Bonzini 97*5e302a7dSAlberto Garcia result = self.vm.qmp('block-stream', device='drive0', base=backing_img) 986e343609SPaolo Bonzini self.assert_qmp(result, 'return', {}) 996e343609SPaolo Bonzini 1009974ad40SFam Zheng self.wait_until_completed() 1016e343609SPaolo Bonzini 102ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 1036e343609SPaolo Bonzini self.vm.shutdown() 1046e343609SPaolo Bonzini 10590c9b167SKevin Wolf self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img), 10690c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 1076e343609SPaolo Bonzini 'image file map does not match backing file after streaming') 1086e343609SPaolo Bonzini 10937ce63ebSStefan Hajnoczi def test_device_not_found(self): 110db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='nonexistent') 11137ce63ebSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'DeviceNotFound') 11237ce63ebSStefan Hajnoczi 113774a8850SStefan Hajnoczi 1142499a096SStefan Hajnocziclass TestSmallerBackingFile(iotests.QMPTestCase): 115774a8850SStefan Hajnoczi backing_len = 1 * 1024 * 1024 # MB 116774a8850SStefan Hajnoczi image_len = 2 * backing_len 117774a8850SStefan Hajnoczi 118774a8850SStefan Hajnoczi def setUp(self): 1192499a096SStefan Hajnoczi iotests.create_image(backing_img, self.backing_len) 120774a8850SStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len)) 121774a8850SStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 122774a8850SStefan Hajnoczi self.vm.launch() 123774a8850SStefan Hajnoczi 124774a8850SStefan Hajnoczi # If this hangs, then you are missing a fix to complete streaming when the 125774a8850SStefan Hajnoczi # end of the backing file is reached. 126774a8850SStefan Hajnoczi def test_stream(self): 127ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 128774a8850SStefan Hajnoczi 129774a8850SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 130774a8850SStefan Hajnoczi self.assert_qmp(result, 'return', {}) 131774a8850SStefan Hajnoczi 1329974ad40SFam Zheng self.wait_until_completed() 133774a8850SStefan Hajnoczi 134ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 135774a8850SStefan Hajnoczi self.vm.shutdown() 136774a8850SStefan Hajnoczi 1372499a096SStefan Hajnocziclass TestErrors(iotests.QMPTestCase): 13890f0b711SPaolo Bonzini image_len = 2 * 1024 * 1024 # MB 13990f0b711SPaolo Bonzini 14090f0b711SPaolo Bonzini # this should match STREAM_BUFFER_SIZE/512 in block/stream.c 14190f0b711SPaolo Bonzini STREAM_BUFFER_SIZE = 512 * 1024 14290f0b711SPaolo Bonzini 14390f0b711SPaolo Bonzini def create_blkdebug_file(self, name, event, errno): 14490f0b711SPaolo Bonzini file = open(name, 'w') 14590f0b711SPaolo Bonzini file.write(''' 14690f0b711SPaolo Bonzini[inject-error] 14790f0b711SPaolo Bonzinistate = "1" 14890f0b711SPaolo Bonzinievent = "%s" 14990f0b711SPaolo Bonzinierrno = "%d" 15090f0b711SPaolo Bonziniimmediately = "off" 15190f0b711SPaolo Bonzinionce = "on" 15290f0b711SPaolo Bonzinisector = "%d" 15390f0b711SPaolo Bonzini 15490f0b711SPaolo Bonzini[set-state] 15590f0b711SPaolo Bonzinistate = "1" 15690f0b711SPaolo Bonzinievent = "%s" 15790f0b711SPaolo Bonzininew_state = "2" 15890f0b711SPaolo Bonzini 15990f0b711SPaolo Bonzini[set-state] 16090f0b711SPaolo Bonzinistate = "2" 16190f0b711SPaolo Bonzinievent = "%s" 16290f0b711SPaolo Bonzininew_state = "1" 16390f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event)) 16490f0b711SPaolo Bonzini file.close() 16590f0b711SPaolo Bonzini 16690f0b711SPaolo Bonziniclass TestEIO(TestErrors): 16790f0b711SPaolo Bonzini def setUp(self): 16890f0b711SPaolo Bonzini self.blkdebug_file = backing_img + ".blkdebug" 1692499a096SStefan Hajnoczi iotests.create_image(backing_img, TestErrors.image_len) 17090f0b711SPaolo Bonzini self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5) 17190f0b711SPaolo Bonzini qemu_img('create', '-f', iotests.imgfmt, 17290f0b711SPaolo Bonzini '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' 17390f0b711SPaolo Bonzini % (self.blkdebug_file, backing_img), 17490f0b711SPaolo Bonzini test_img) 17590f0b711SPaolo Bonzini self.vm = iotests.VM().add_drive(test_img) 17690f0b711SPaolo Bonzini self.vm.launch() 17790f0b711SPaolo Bonzini 17890f0b711SPaolo Bonzini def tearDown(self): 17990f0b711SPaolo Bonzini self.vm.shutdown() 18090f0b711SPaolo Bonzini os.remove(test_img) 18190f0b711SPaolo Bonzini os.remove(backing_img) 18290f0b711SPaolo Bonzini os.remove(self.blkdebug_file) 18390f0b711SPaolo Bonzini 18490f0b711SPaolo Bonzini def test_report(self): 185ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 18690f0b711SPaolo Bonzini 18790f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0') 18890f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 18990f0b711SPaolo Bonzini 19090f0b711SPaolo Bonzini completed = False 19190f0b711SPaolo Bonzini error = False 19290f0b711SPaolo Bonzini while not completed: 19390f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 19490f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 19590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 19690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 19790f0b711SPaolo Bonzini error = True 19890f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 19990f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 20090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 20190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 20290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 20390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) 20490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 20590f0b711SPaolo Bonzini completed = True 20690f0b711SPaolo Bonzini 207ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 20890f0b711SPaolo Bonzini self.vm.shutdown() 20990f0b711SPaolo Bonzini 21090f0b711SPaolo Bonzini def test_ignore(self): 211ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 21290f0b711SPaolo Bonzini 21390f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='ignore') 21490f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 21590f0b711SPaolo Bonzini 21690f0b711SPaolo Bonzini error = False 21790f0b711SPaolo Bonzini completed = False 21890f0b711SPaolo Bonzini while not completed: 21990f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 22090f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 22190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 22290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 22390f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 22490f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 22590f0b711SPaolo Bonzini error = True 22690f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 22790f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 22890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 22990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 23090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 23190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 23290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 23390f0b711SPaolo Bonzini completed = True 23490f0b711SPaolo Bonzini 235ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 23690f0b711SPaolo Bonzini self.vm.shutdown() 23790f0b711SPaolo Bonzini 23890f0b711SPaolo Bonzini def test_stop(self): 239ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 24090f0b711SPaolo Bonzini 24190f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='stop') 24290f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 24390f0b711SPaolo Bonzini 24490f0b711SPaolo Bonzini error = False 24590f0b711SPaolo Bonzini completed = False 24690f0b711SPaolo Bonzini while not completed: 24790f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 24890f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 24901809194SJohn Snow error = True 25090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 25190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 25290f0b711SPaolo Bonzini 25390f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 25490f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 25590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 25690f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'failed') 25790f0b711SPaolo Bonzini 25890f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 25990f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 26090f0b711SPaolo Bonzini 26190f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 26201809194SJohn Snow if result == {'return': []}: 26301809194SJohn Snow # Race; likely already finished. Check. 26401809194SJohn Snow continue 26590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 26690f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 26790f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 26890f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 26990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 27090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 27190f0b711SPaolo Bonzini self.assert_qmp_absent(event, 'data/error') 27290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 27390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 27490f0b711SPaolo Bonzini completed = True 27590f0b711SPaolo Bonzini 276ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 27790f0b711SPaolo Bonzini self.vm.shutdown() 27890f0b711SPaolo Bonzini 27990f0b711SPaolo Bonzini def test_enospc(self): 280ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 28190f0b711SPaolo Bonzini 28290f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 28390f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 28490f0b711SPaolo Bonzini 28590f0b711SPaolo Bonzini completed = False 28690f0b711SPaolo Bonzini error = False 28790f0b711SPaolo Bonzini while not completed: 28890f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 28990f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 29090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 29190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 29290f0b711SPaolo Bonzini error = True 29390f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 29490f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 29590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 29690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 29790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 29890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) 29990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 30090f0b711SPaolo Bonzini completed = True 30190f0b711SPaolo Bonzini 302ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 30390f0b711SPaolo Bonzini self.vm.shutdown() 30490f0b711SPaolo Bonzini 30590f0b711SPaolo Bonziniclass TestENOSPC(TestErrors): 30690f0b711SPaolo Bonzini def setUp(self): 30790f0b711SPaolo Bonzini self.blkdebug_file = backing_img + ".blkdebug" 3082499a096SStefan Hajnoczi iotests.create_image(backing_img, TestErrors.image_len) 30990f0b711SPaolo Bonzini self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28) 31090f0b711SPaolo Bonzini qemu_img('create', '-f', iotests.imgfmt, 31190f0b711SPaolo Bonzini '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' 31290f0b711SPaolo Bonzini % (self.blkdebug_file, backing_img), 31390f0b711SPaolo Bonzini test_img) 31490f0b711SPaolo Bonzini self.vm = iotests.VM().add_drive(test_img) 31590f0b711SPaolo Bonzini self.vm.launch() 31690f0b711SPaolo Bonzini 31790f0b711SPaolo Bonzini def tearDown(self): 31890f0b711SPaolo Bonzini self.vm.shutdown() 31990f0b711SPaolo Bonzini os.remove(test_img) 32090f0b711SPaolo Bonzini os.remove(backing_img) 32190f0b711SPaolo Bonzini os.remove(self.blkdebug_file) 32290f0b711SPaolo Bonzini 32390f0b711SPaolo Bonzini def test_enospc(self): 324ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 32590f0b711SPaolo Bonzini 32690f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 32790f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 32890f0b711SPaolo Bonzini 32990f0b711SPaolo Bonzini error = False 33090f0b711SPaolo Bonzini completed = False 33190f0b711SPaolo Bonzini while not completed: 33290f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 33390f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 33490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 33590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 33690f0b711SPaolo Bonzini 33790f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 33890f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 33990f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 34090f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'nospace') 34190f0b711SPaolo Bonzini 34290f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 34390f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 34490f0b711SPaolo Bonzini 34590f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 34690f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 34790f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 34890f0b711SPaolo Bonzini error = True 34990f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 35090f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 35190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 35290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 35390f0b711SPaolo Bonzini self.assert_qmp_absent(event, 'data/error') 35490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 35590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 35690f0b711SPaolo Bonzini completed = True 35790f0b711SPaolo Bonzini 358ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 35990f0b711SPaolo Bonzini self.vm.shutdown() 360774a8850SStefan Hajnoczi 3612499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase): 36237ce63ebSStefan Hajnoczi image_len = 8 * 1024 * 1024 * 1024 # GB 36337ce63ebSStefan Hajnoczi 36437ce63ebSStefan Hajnoczi def setUp(self): 36537ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestStreamStop.image_len)) 36690c9b167SKevin Wolf qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) 36737ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 36890c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) 369b59b3d57SFam Zheng self.vm = iotests.VM().add_drive("blkdebug::" + test_img) 37037ce63ebSStefan Hajnoczi self.vm.launch() 37137ce63ebSStefan Hajnoczi 37237ce63ebSStefan Hajnoczi def tearDown(self): 37337ce63ebSStefan Hajnoczi self.vm.shutdown() 37437ce63ebSStefan Hajnoczi os.remove(test_img) 37537ce63ebSStefan Hajnoczi os.remove(backing_img) 37637ce63ebSStefan Hajnoczi 37737ce63ebSStefan Hajnoczi def test_stream_stop(self): 378ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 37937ce63ebSStefan Hajnoczi 380b59b3d57SFam Zheng self.vm.pause_drive('drive0') 381db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 38237ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 38337ce63ebSStefan Hajnoczi 3840fd05e8dSPaolo Bonzini time.sleep(0.1) 38537ce63ebSStefan Hajnoczi events = self.vm.get_qmp_events(wait=False) 38637ce63ebSStefan Hajnoczi self.assertEqual(events, [], 'unexpected QMP event: %s' % events) 38737ce63ebSStefan Hajnoczi 388b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 38937ce63ebSStefan Hajnoczi 3902499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase): 39137ce63ebSStefan Hajnoczi image_len = 80 * 1024 * 1024 # MB 39237ce63ebSStefan Hajnoczi 39337ce63ebSStefan Hajnoczi def setUp(self): 39437ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestSetSpeed.image_len)) 39590c9b167SKevin Wolf qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) 39637ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 39790c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) 398b59b3d57SFam Zheng self.vm = iotests.VM().add_drive('blkdebug::' + test_img) 39937ce63ebSStefan Hajnoczi self.vm.launch() 40037ce63ebSStefan Hajnoczi 40137ce63ebSStefan Hajnoczi def tearDown(self): 40237ce63ebSStefan Hajnoczi self.vm.shutdown() 40337ce63ebSStefan Hajnoczi os.remove(test_img) 40437ce63ebSStefan Hajnoczi os.remove(backing_img) 40537ce63ebSStefan Hajnoczi 406e425306aSStefan Hajnoczi # This is a short performance test which is not run by default. 407e425306aSStefan Hajnoczi # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput" 408e425306aSStefan Hajnoczi def perf_test_throughput(self): 409ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 41037ce63ebSStefan Hajnoczi 411db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 41237ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 41337ce63ebSStefan Hajnoczi 414e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 41537ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 41637ce63ebSStefan Hajnoczi 4179974ad40SFam Zheng self.wait_until_completed() 41837ce63ebSStefan Hajnoczi 419ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 42037ce63ebSStefan Hajnoczi 421e425306aSStefan Hajnoczi def test_set_speed(self): 422ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 423e425306aSStefan Hajnoczi 424b59b3d57SFam Zheng self.vm.pause_drive('drive0') 425e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 426e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 427e425306aSStefan Hajnoczi 428e425306aSStefan Hajnoczi # Default speed is 0 429e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 430e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 431e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 432e425306aSStefan Hajnoczi 433e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 434e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 435e425306aSStefan Hajnoczi 436e425306aSStefan Hajnoczi # Ensure the speed we set was accepted 437e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 438e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 439e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 440e425306aSStefan Hajnoczi 441b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 442b59b3d57SFam Zheng self.vm.pause_drive('drive0') 443e425306aSStefan Hajnoczi 444e425306aSStefan Hajnoczi # Check setting speed in block-stream works 445e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024) 446e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 447e425306aSStefan Hajnoczi 448e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 449e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 450e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) 451e425306aSStefan Hajnoczi 452b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 453e425306aSStefan Hajnoczi 454e425306aSStefan Hajnoczi def test_set_speed_invalid(self): 455ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 456e425306aSStefan Hajnoczi 457e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=-1) 45858c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 459e425306aSStefan Hajnoczi 460ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 461e425306aSStefan Hajnoczi 462e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 463e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 464e425306aSStefan Hajnoczi 465e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 46658c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 467e425306aSStefan Hajnoczi 468e425306aSStefan Hajnoczi self.cancel_and_wait() 469e425306aSStefan Hajnoczi 47037ce63ebSStefan Hajnocziif __name__ == '__main__': 47137ce63ebSStefan Hajnoczi iotests.main(supported_fmts=['qcow2', 'qed']) 472