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) 38b5e51dd7SFam Zheng self.vm = iotests.VM().add_drive("blkdebug::" + 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 539974ad40SFam Zheng self.wait_until_completed() 5437ce63ebSStefan Hajnoczi 55ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 56863a5d04SPaolo Bonzini self.vm.shutdown() 5737ce63ebSStefan Hajnoczi 5890c9b167SKevin Wolf self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), 5990c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-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') 849974ad40SFam Zheng self.wait_until_completed() 850c817347SPaolo Bonzini 86ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 870c817347SPaolo Bonzini self.vm.shutdown() 880c817347SPaolo Bonzini 8990c9b167SKevin Wolf self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), 9090c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-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 999974ad40SFam Zheng self.wait_until_completed() 1006e343609SPaolo Bonzini 101ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 1026e343609SPaolo Bonzini self.vm.shutdown() 1036e343609SPaolo Bonzini 10490c9b167SKevin Wolf self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img), 10590c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-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 1319974ad40SFam 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': 248*01809194SJohn Snow error = True 24990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 25090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 25190f0b711SPaolo Bonzini 25290f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 25390f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 25490f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 25590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'failed') 25690f0b711SPaolo Bonzini 25790f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 25890f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 25990f0b711SPaolo Bonzini 26090f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 261*01809194SJohn Snow if result == {'return': []}: 262*01809194SJohn Snow # Race; likely already finished. Check. 263*01809194SJohn Snow continue 26490f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 26590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 26690f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 26790f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 26890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 26990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 27090f0b711SPaolo Bonzini self.assert_qmp_absent(event, 'data/error') 27190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 27290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 27390f0b711SPaolo Bonzini completed = True 27490f0b711SPaolo Bonzini 275ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 27690f0b711SPaolo Bonzini self.vm.shutdown() 27790f0b711SPaolo Bonzini 27890f0b711SPaolo Bonzini def test_enospc(self): 279ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 28090f0b711SPaolo Bonzini 28190f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 28290f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 28390f0b711SPaolo Bonzini 28490f0b711SPaolo Bonzini completed = False 28590f0b711SPaolo Bonzini error = False 28690f0b711SPaolo Bonzini while not completed: 28790f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 28890f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 28990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 29090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 29190f0b711SPaolo Bonzini error = True 29290f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 29390f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 29490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 29590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 29690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 29790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) 29890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 29990f0b711SPaolo Bonzini completed = True 30090f0b711SPaolo Bonzini 301ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 30290f0b711SPaolo Bonzini self.vm.shutdown() 30390f0b711SPaolo Bonzini 30490f0b711SPaolo Bonziniclass TestENOSPC(TestErrors): 30590f0b711SPaolo Bonzini def setUp(self): 30690f0b711SPaolo Bonzini self.blkdebug_file = backing_img + ".blkdebug" 3072499a096SStefan Hajnoczi iotests.create_image(backing_img, TestErrors.image_len) 30890f0b711SPaolo Bonzini self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28) 30990f0b711SPaolo Bonzini qemu_img('create', '-f', iotests.imgfmt, 31090f0b711SPaolo Bonzini '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' 31190f0b711SPaolo Bonzini % (self.blkdebug_file, backing_img), 31290f0b711SPaolo Bonzini test_img) 31390f0b711SPaolo Bonzini self.vm = iotests.VM().add_drive(test_img) 31490f0b711SPaolo Bonzini self.vm.launch() 31590f0b711SPaolo Bonzini 31690f0b711SPaolo Bonzini def tearDown(self): 31790f0b711SPaolo Bonzini self.vm.shutdown() 31890f0b711SPaolo Bonzini os.remove(test_img) 31990f0b711SPaolo Bonzini os.remove(backing_img) 32090f0b711SPaolo Bonzini os.remove(self.blkdebug_file) 32190f0b711SPaolo Bonzini 32290f0b711SPaolo Bonzini def test_enospc(self): 323ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 32490f0b711SPaolo Bonzini 32590f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 32690f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 32790f0b711SPaolo Bonzini 32890f0b711SPaolo Bonzini error = False 32990f0b711SPaolo Bonzini completed = False 33090f0b711SPaolo Bonzini while not completed: 33190f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 33290f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 33390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 33490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 33590f0b711SPaolo Bonzini 33690f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 33790f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 33890f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 33990f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'nospace') 34090f0b711SPaolo Bonzini 34190f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 34290f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 34390f0b711SPaolo Bonzini 34490f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 34590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 34690f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 34790f0b711SPaolo Bonzini error = True 34890f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 34990f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 35090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 35190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 35290f0b711SPaolo Bonzini self.assert_qmp_absent(event, 'data/error') 35390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 35490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 35590f0b711SPaolo Bonzini completed = True 35690f0b711SPaolo Bonzini 357ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 35890f0b711SPaolo Bonzini self.vm.shutdown() 359774a8850SStefan Hajnoczi 3602499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase): 36137ce63ebSStefan Hajnoczi image_len = 8 * 1024 * 1024 * 1024 # GB 36237ce63ebSStefan Hajnoczi 36337ce63ebSStefan Hajnoczi def setUp(self): 36437ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestStreamStop.image_len)) 36590c9b167SKevin Wolf qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) 36637ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 36790c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) 368b59b3d57SFam Zheng self.vm = iotests.VM().add_drive("blkdebug::" + test_img) 36937ce63ebSStefan Hajnoczi self.vm.launch() 37037ce63ebSStefan Hajnoczi 37137ce63ebSStefan Hajnoczi def tearDown(self): 37237ce63ebSStefan Hajnoczi self.vm.shutdown() 37337ce63ebSStefan Hajnoczi os.remove(test_img) 37437ce63ebSStefan Hajnoczi os.remove(backing_img) 37537ce63ebSStefan Hajnoczi 37637ce63ebSStefan Hajnoczi def test_stream_stop(self): 377ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 37837ce63ebSStefan Hajnoczi 379b59b3d57SFam Zheng self.vm.pause_drive('drive0') 380db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 38137ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 38237ce63ebSStefan Hajnoczi 3830fd05e8dSPaolo Bonzini time.sleep(0.1) 38437ce63ebSStefan Hajnoczi events = self.vm.get_qmp_events(wait=False) 38537ce63ebSStefan Hajnoczi self.assertEqual(events, [], 'unexpected QMP event: %s' % events) 38637ce63ebSStefan Hajnoczi 387b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 38837ce63ebSStefan Hajnoczi 3892499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase): 39037ce63ebSStefan Hajnoczi image_len = 80 * 1024 * 1024 # MB 39137ce63ebSStefan Hajnoczi 39237ce63ebSStefan Hajnoczi def setUp(self): 39337ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestSetSpeed.image_len)) 39490c9b167SKevin Wolf qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) 39537ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 39690c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) 397b59b3d57SFam 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 405e425306aSStefan Hajnoczi # This is a short performance test which is not run by default. 406e425306aSStefan Hajnoczi # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput" 407e425306aSStefan Hajnoczi def perf_test_throughput(self): 408ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 40937ce63ebSStefan Hajnoczi 410db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 41137ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 41237ce63ebSStefan Hajnoczi 413e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 41437ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 41537ce63ebSStefan Hajnoczi 4169974ad40SFam Zheng self.wait_until_completed() 41737ce63ebSStefan Hajnoczi 418ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 41937ce63ebSStefan Hajnoczi 420e425306aSStefan Hajnoczi def test_set_speed(self): 421ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 422e425306aSStefan Hajnoczi 423b59b3d57SFam Zheng self.vm.pause_drive('drive0') 424e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 425e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 426e425306aSStefan Hajnoczi 427e425306aSStefan Hajnoczi # Default speed is 0 428e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 429e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 430e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 431e425306aSStefan Hajnoczi 432e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 433e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 434e425306aSStefan Hajnoczi 435e425306aSStefan Hajnoczi # Ensure the speed we set was accepted 436e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 437e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 438e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 439e425306aSStefan Hajnoczi 440b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 441b59b3d57SFam Zheng self.vm.pause_drive('drive0') 442e425306aSStefan Hajnoczi 443e425306aSStefan Hajnoczi # Check setting speed in block-stream works 444e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024) 445e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 446e425306aSStefan Hajnoczi 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', 4 * 1024 * 1024) 450e425306aSStefan Hajnoczi 451b59b3d57SFam Zheng self.cancel_and_wait(resume=True) 452e425306aSStefan Hajnoczi 453e425306aSStefan Hajnoczi def test_set_speed_invalid(self): 454ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 455e425306aSStefan Hajnoczi 456e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=-1) 45758c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 458e425306aSStefan Hajnoczi 459ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 460e425306aSStefan Hajnoczi 461e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 462e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 463e425306aSStefan Hajnoczi 464e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 46558c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 466e425306aSStefan Hajnoczi 467e425306aSStefan Hajnoczi self.cancel_and_wait() 468e425306aSStefan Hajnoczi 46937ce63ebSStefan Hajnocziif __name__ == '__main__': 47037ce63ebSStefan Hajnoczi iotests.main(supported_fmts=['qcow2', 'qed']) 471