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