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 30*2499a096SStefan Hajnocziclass TestSingleDrive(iotests.QMPTestCase): 3137ce63ebSStefan Hajnoczi image_len = 1 * 1024 * 1024 # MB 3237ce63ebSStefan Hajnoczi 3337ce63ebSStefan Hajnoczi def setUp(self): 34*2499a096SStefan 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) 3737ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 3837ce63ebSStefan Hajnoczi self.vm.launch() 3937ce63ebSStefan Hajnoczi 4037ce63ebSStefan Hajnoczi def tearDown(self): 4137ce63ebSStefan Hajnoczi self.vm.shutdown() 4237ce63ebSStefan Hajnoczi os.remove(test_img) 436e343609SPaolo Bonzini os.remove(mid_img) 4437ce63ebSStefan Hajnoczi os.remove(backing_img) 4537ce63ebSStefan Hajnoczi 4637ce63ebSStefan Hajnoczi def test_stream(self): 47ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 4837ce63ebSStefan Hajnoczi 49db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 5037ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 5137ce63ebSStefan Hajnoczi 5237ce63ebSStefan Hajnoczi completed = False 5337ce63ebSStefan Hajnoczi while not completed: 5437ce63ebSStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 5537ce63ebSStefan Hajnoczi if event['event'] == 'BLOCK_JOB_COMPLETED': 5637ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 5737ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/device', 'drive0') 5837ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/offset', self.image_len) 5937ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/len', self.image_len) 6037ce63ebSStefan Hajnoczi completed = True 6137ce63ebSStefan Hajnoczi 62ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 63863a5d04SPaolo Bonzini self.vm.shutdown() 6437ce63ebSStefan Hajnoczi 65efcc7a23SPaolo Bonzini self.assertEqual(qemu_io('-c', 'map', backing_img), 66efcc7a23SPaolo Bonzini qemu_io('-c', 'map', test_img), 67efcc7a23SPaolo Bonzini 'image file map does not match backing file after streaming') 6837ce63ebSStefan Hajnoczi 690c817347SPaolo Bonzini def test_stream_pause(self): 70ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 710c817347SPaolo Bonzini 720c817347SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0') 730c817347SPaolo Bonzini self.assert_qmp(result, 'return', {}) 740c817347SPaolo Bonzini 750c817347SPaolo Bonzini result = self.vm.qmp('block-job-pause', device='drive0') 760c817347SPaolo Bonzini self.assert_qmp(result, 'return', {}) 770c817347SPaolo Bonzini 780c817347SPaolo Bonzini time.sleep(1) 790c817347SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 800c817347SPaolo Bonzini offset = self.dictpath(result, 'return[0]/offset') 810c817347SPaolo Bonzini 820c817347SPaolo Bonzini time.sleep(1) 830c817347SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 840c817347SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', offset) 850c817347SPaolo Bonzini 860c817347SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 870c817347SPaolo Bonzini self.assert_qmp(result, 'return', {}) 880c817347SPaolo Bonzini 890c817347SPaolo Bonzini completed = False 900c817347SPaolo Bonzini while not completed: 910c817347SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 920c817347SPaolo Bonzini if event['event'] == 'BLOCK_JOB_COMPLETED': 930c817347SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 940c817347SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 950c817347SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 960c817347SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 970c817347SPaolo Bonzini completed = True 980c817347SPaolo Bonzini 99ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 1000c817347SPaolo Bonzini self.vm.shutdown() 1010c817347SPaolo Bonzini 1020c817347SPaolo Bonzini self.assertEqual(qemu_io('-c', 'map', backing_img), 1030c817347SPaolo Bonzini qemu_io('-c', 'map', test_img), 1040c817347SPaolo Bonzini 'image file map does not match backing file after streaming') 1050c817347SPaolo Bonzini 1066e343609SPaolo Bonzini def test_stream_partial(self): 107ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 1086e343609SPaolo Bonzini 1096e343609SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', base=mid_img) 1106e343609SPaolo Bonzini self.assert_qmp(result, 'return', {}) 1116e343609SPaolo Bonzini 1126e343609SPaolo Bonzini completed = False 1136e343609SPaolo Bonzini while not completed: 1146e343609SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 1156e343609SPaolo Bonzini if event['event'] == 'BLOCK_JOB_COMPLETED': 1166e343609SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 1176e343609SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 1186e343609SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 1196e343609SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 1206e343609SPaolo Bonzini completed = True 1216e343609SPaolo Bonzini 122ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 1236e343609SPaolo Bonzini self.vm.shutdown() 1246e343609SPaolo Bonzini 1256e343609SPaolo Bonzini self.assertEqual(qemu_io('-c', 'map', mid_img), 1266e343609SPaolo Bonzini qemu_io('-c', 'map', test_img), 1276e343609SPaolo Bonzini 'image file map does not match backing file after streaming') 1286e343609SPaolo Bonzini 12937ce63ebSStefan Hajnoczi def test_device_not_found(self): 130db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='nonexistent') 13137ce63ebSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'DeviceNotFound') 13237ce63ebSStefan Hajnoczi 133774a8850SStefan Hajnoczi 134*2499a096SStefan Hajnocziclass TestSmallerBackingFile(iotests.QMPTestCase): 135774a8850SStefan Hajnoczi backing_len = 1 * 1024 * 1024 # MB 136774a8850SStefan Hajnoczi image_len = 2 * backing_len 137774a8850SStefan Hajnoczi 138774a8850SStefan Hajnoczi def setUp(self): 139*2499a096SStefan Hajnoczi iotests.create_image(backing_img, self.backing_len) 140774a8850SStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len)) 141774a8850SStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 142774a8850SStefan Hajnoczi self.vm.launch() 143774a8850SStefan Hajnoczi 144774a8850SStefan Hajnoczi # If this hangs, then you are missing a fix to complete streaming when the 145774a8850SStefan Hajnoczi # end of the backing file is reached. 146774a8850SStefan Hajnoczi def test_stream(self): 147ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 148774a8850SStefan Hajnoczi 149774a8850SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 150774a8850SStefan Hajnoczi self.assert_qmp(result, 'return', {}) 151774a8850SStefan Hajnoczi 152774a8850SStefan Hajnoczi completed = False 153774a8850SStefan Hajnoczi while not completed: 154774a8850SStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 155774a8850SStefan Hajnoczi if event['event'] == 'BLOCK_JOB_COMPLETED': 156774a8850SStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 157774a8850SStefan Hajnoczi self.assert_qmp(event, 'data/device', 'drive0') 158774a8850SStefan Hajnoczi self.assert_qmp(event, 'data/offset', self.image_len) 159774a8850SStefan Hajnoczi self.assert_qmp(event, 'data/len', self.image_len) 160774a8850SStefan Hajnoczi completed = True 161774a8850SStefan Hajnoczi 162ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 163774a8850SStefan Hajnoczi self.vm.shutdown() 164774a8850SStefan Hajnoczi 165*2499a096SStefan Hajnocziclass TestErrors(iotests.QMPTestCase): 16690f0b711SPaolo Bonzini image_len = 2 * 1024 * 1024 # MB 16790f0b711SPaolo Bonzini 16890f0b711SPaolo Bonzini # this should match STREAM_BUFFER_SIZE/512 in block/stream.c 16990f0b711SPaolo Bonzini STREAM_BUFFER_SIZE = 512 * 1024 17090f0b711SPaolo Bonzini 17190f0b711SPaolo Bonzini def create_blkdebug_file(self, name, event, errno): 17290f0b711SPaolo Bonzini file = open(name, 'w') 17390f0b711SPaolo Bonzini file.write(''' 17490f0b711SPaolo Bonzini[inject-error] 17590f0b711SPaolo Bonzinistate = "1" 17690f0b711SPaolo Bonzinievent = "%s" 17790f0b711SPaolo Bonzinierrno = "%d" 17890f0b711SPaolo Bonziniimmediately = "off" 17990f0b711SPaolo Bonzinionce = "on" 18090f0b711SPaolo Bonzinisector = "%d" 18190f0b711SPaolo Bonzini 18290f0b711SPaolo Bonzini[set-state] 18390f0b711SPaolo Bonzinistate = "1" 18490f0b711SPaolo Bonzinievent = "%s" 18590f0b711SPaolo Bonzininew_state = "2" 18690f0b711SPaolo Bonzini 18790f0b711SPaolo Bonzini[set-state] 18890f0b711SPaolo Bonzinistate = "2" 18990f0b711SPaolo Bonzinievent = "%s" 19090f0b711SPaolo Bonzininew_state = "1" 19190f0b711SPaolo Bonzini''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event)) 19290f0b711SPaolo Bonzini file.close() 19390f0b711SPaolo Bonzini 19490f0b711SPaolo Bonziniclass TestEIO(TestErrors): 19590f0b711SPaolo Bonzini def setUp(self): 19690f0b711SPaolo Bonzini self.blkdebug_file = backing_img + ".blkdebug" 197*2499a096SStefan Hajnoczi iotests.create_image(backing_img, TestErrors.image_len) 19890f0b711SPaolo Bonzini self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5) 19990f0b711SPaolo Bonzini qemu_img('create', '-f', iotests.imgfmt, 20090f0b711SPaolo Bonzini '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' 20190f0b711SPaolo Bonzini % (self.blkdebug_file, backing_img), 20290f0b711SPaolo Bonzini test_img) 20390f0b711SPaolo Bonzini self.vm = iotests.VM().add_drive(test_img) 20490f0b711SPaolo Bonzini self.vm.launch() 20590f0b711SPaolo Bonzini 20690f0b711SPaolo Bonzini def tearDown(self): 20790f0b711SPaolo Bonzini self.vm.shutdown() 20890f0b711SPaolo Bonzini os.remove(test_img) 20990f0b711SPaolo Bonzini os.remove(backing_img) 21090f0b711SPaolo Bonzini os.remove(self.blkdebug_file) 21190f0b711SPaolo Bonzini 21290f0b711SPaolo Bonzini def test_report(self): 213ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 21490f0b711SPaolo Bonzini 21590f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0') 21690f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 21790f0b711SPaolo Bonzini 21890f0b711SPaolo Bonzini completed = False 21990f0b711SPaolo Bonzini error = False 22090f0b711SPaolo Bonzini while not completed: 22190f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 22290f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 22390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 22490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 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.STREAM_BUFFER_SIZE) 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_ignore(self): 239ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 24090f0b711SPaolo Bonzini 24190f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='ignore') 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': 24990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 25090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 25190f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 25290f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 25390f0b711SPaolo Bonzini error = True 25490f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 25590f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 25690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 25790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 25890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 25990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 26090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 26190f0b711SPaolo Bonzini completed = True 26290f0b711SPaolo Bonzini 263ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 26490f0b711SPaolo Bonzini self.vm.shutdown() 26590f0b711SPaolo Bonzini 26690f0b711SPaolo Bonzini def test_stop(self): 267ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 26890f0b711SPaolo Bonzini 26990f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='stop') 27090f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 27190f0b711SPaolo Bonzini 27290f0b711SPaolo Bonzini error = False 27390f0b711SPaolo Bonzini completed = False 27490f0b711SPaolo Bonzini while not completed: 27590f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 27690f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 27790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 27890f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 27990f0b711SPaolo Bonzini 28090f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 28190f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 28290f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 28390f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'failed') 28490f0b711SPaolo Bonzini 28590f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 28690f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 28790f0b711SPaolo Bonzini 28890f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 28990f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 29090f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 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_absent(event, 'data/error') 29790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 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 Bonzini def test_enospc(self): 305ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 30690f0b711SPaolo Bonzini 30790f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 30890f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 30990f0b711SPaolo Bonzini 31090f0b711SPaolo Bonzini completed = False 31190f0b711SPaolo Bonzini error = False 31290f0b711SPaolo Bonzini while not completed: 31390f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 31490f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 31590f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 31690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 31790f0b711SPaolo Bonzini error = True 31890f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 31990f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 32090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 32190f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 32290f0b711SPaolo Bonzini self.assert_qmp(event, 'data/error', 'Input/output error') 32390f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) 32490f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 32590f0b711SPaolo Bonzini completed = True 32690f0b711SPaolo Bonzini 327ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 32890f0b711SPaolo Bonzini self.vm.shutdown() 32990f0b711SPaolo Bonzini 33090f0b711SPaolo Bonziniclass TestENOSPC(TestErrors): 33190f0b711SPaolo Bonzini def setUp(self): 33290f0b711SPaolo Bonzini self.blkdebug_file = backing_img + ".blkdebug" 333*2499a096SStefan Hajnoczi iotests.create_image(backing_img, TestErrors.image_len) 33490f0b711SPaolo Bonzini self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28) 33590f0b711SPaolo Bonzini qemu_img('create', '-f', iotests.imgfmt, 33690f0b711SPaolo Bonzini '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' 33790f0b711SPaolo Bonzini % (self.blkdebug_file, backing_img), 33890f0b711SPaolo Bonzini test_img) 33990f0b711SPaolo Bonzini self.vm = iotests.VM().add_drive(test_img) 34090f0b711SPaolo Bonzini self.vm.launch() 34190f0b711SPaolo Bonzini 34290f0b711SPaolo Bonzini def tearDown(self): 34390f0b711SPaolo Bonzini self.vm.shutdown() 34490f0b711SPaolo Bonzini os.remove(test_img) 34590f0b711SPaolo Bonzini os.remove(backing_img) 34690f0b711SPaolo Bonzini os.remove(self.blkdebug_file) 34790f0b711SPaolo Bonzini 34890f0b711SPaolo Bonzini def test_enospc(self): 349ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 35090f0b711SPaolo Bonzini 35190f0b711SPaolo Bonzini result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') 35290f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 35390f0b711SPaolo Bonzini 35490f0b711SPaolo Bonzini error = False 35590f0b711SPaolo Bonzini completed = False 35690f0b711SPaolo Bonzini while not completed: 35790f0b711SPaolo Bonzini for event in self.vm.get_qmp_events(wait=True): 35890f0b711SPaolo Bonzini if event['event'] == 'BLOCK_JOB_ERROR': 35990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 36090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/operation', 'read') 36190f0b711SPaolo Bonzini 36290f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 36390f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', True) 36490f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) 36590f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'nospace') 36690f0b711SPaolo Bonzini 36790f0b711SPaolo Bonzini result = self.vm.qmp('block-job-resume', device='drive0') 36890f0b711SPaolo Bonzini self.assert_qmp(result, 'return', {}) 36990f0b711SPaolo Bonzini 37090f0b711SPaolo Bonzini result = self.vm.qmp('query-block-jobs') 37190f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/paused', False) 37290f0b711SPaolo Bonzini self.assert_qmp(result, 'return[0]/io-status', 'ok') 37390f0b711SPaolo Bonzini error = True 37490f0b711SPaolo Bonzini elif event['event'] == 'BLOCK_JOB_COMPLETED': 37590f0b711SPaolo Bonzini self.assertTrue(error, 'job completed unexpectedly') 37690f0b711SPaolo Bonzini self.assert_qmp(event, 'data/type', 'stream') 37790f0b711SPaolo Bonzini self.assert_qmp(event, 'data/device', 'drive0') 37890f0b711SPaolo Bonzini self.assert_qmp_absent(event, 'data/error') 37990f0b711SPaolo Bonzini self.assert_qmp(event, 'data/offset', self.image_len) 38090f0b711SPaolo Bonzini self.assert_qmp(event, 'data/len', self.image_len) 38190f0b711SPaolo Bonzini completed = True 38290f0b711SPaolo Bonzini 383ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 38490f0b711SPaolo Bonzini self.vm.shutdown() 385774a8850SStefan Hajnoczi 386*2499a096SStefan Hajnocziclass TestStreamStop(iotests.QMPTestCase): 38737ce63ebSStefan Hajnoczi image_len = 8 * 1024 * 1024 * 1024 # GB 38837ce63ebSStefan Hajnoczi 38937ce63ebSStefan Hajnoczi def setUp(self): 39037ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestStreamStop.image_len)) 39137ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 39237ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 39337ce63ebSStefan Hajnoczi self.vm.launch() 39437ce63ebSStefan Hajnoczi 39537ce63ebSStefan Hajnoczi def tearDown(self): 39637ce63ebSStefan Hajnoczi self.vm.shutdown() 39737ce63ebSStefan Hajnoczi os.remove(test_img) 39837ce63ebSStefan Hajnoczi os.remove(backing_img) 39937ce63ebSStefan Hajnoczi 40037ce63ebSStefan Hajnoczi def test_stream_stop(self): 401ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 40237ce63ebSStefan Hajnoczi 403db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 40437ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 40537ce63ebSStefan Hajnoczi 4060fd05e8dSPaolo Bonzini time.sleep(0.1) 40737ce63ebSStefan Hajnoczi events = self.vm.get_qmp_events(wait=False) 40837ce63ebSStefan Hajnoczi self.assertEqual(events, [], 'unexpected QMP event: %s' % events) 40937ce63ebSStefan Hajnoczi 410e425306aSStefan Hajnoczi self.cancel_and_wait() 41137ce63ebSStefan Hajnoczi 412*2499a096SStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase): 41337ce63ebSStefan Hajnoczi image_len = 80 * 1024 * 1024 # MB 41437ce63ebSStefan Hajnoczi 41537ce63ebSStefan Hajnoczi def setUp(self): 41637ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestSetSpeed.image_len)) 41737ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 41837ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 41937ce63ebSStefan Hajnoczi self.vm.launch() 42037ce63ebSStefan Hajnoczi 42137ce63ebSStefan Hajnoczi def tearDown(self): 42237ce63ebSStefan Hajnoczi self.vm.shutdown() 42337ce63ebSStefan Hajnoczi os.remove(test_img) 42437ce63ebSStefan Hajnoczi os.remove(backing_img) 42537ce63ebSStefan Hajnoczi 426e425306aSStefan Hajnoczi # This is a short performance test which is not run by default. 427e425306aSStefan Hajnoczi # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput" 428e425306aSStefan Hajnoczi def perf_test_throughput(self): 429ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 43037ce63ebSStefan Hajnoczi 431db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 43237ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 43337ce63ebSStefan Hajnoczi 434e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 43537ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 43637ce63ebSStefan Hajnoczi 43737ce63ebSStefan Hajnoczi completed = False 43837ce63ebSStefan Hajnoczi while not completed: 43937ce63ebSStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 44037ce63ebSStefan Hajnoczi if event['event'] == 'BLOCK_JOB_COMPLETED': 44137ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 44237ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/device', 'drive0') 44337ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/offset', self.image_len) 44437ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/len', self.image_len) 44537ce63ebSStefan Hajnoczi completed = True 44637ce63ebSStefan Hajnoczi 447ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 44837ce63ebSStefan Hajnoczi 449e425306aSStefan Hajnoczi def test_set_speed(self): 450ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 451e425306aSStefan Hajnoczi 452e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 453e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 454e425306aSStefan Hajnoczi 455e425306aSStefan Hajnoczi # Default speed is 0 456e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 457e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 458e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 459e425306aSStefan Hajnoczi 460e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 461e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 462e425306aSStefan Hajnoczi 463e425306aSStefan Hajnoczi # Ensure the speed we set was accepted 464e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 465e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 466e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 467e425306aSStefan Hajnoczi 468e425306aSStefan Hajnoczi self.cancel_and_wait() 469e425306aSStefan Hajnoczi 470e425306aSStefan Hajnoczi # Check setting speed in block-stream works 471e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024) 472e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 473e425306aSStefan Hajnoczi 474e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 475e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 476e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) 477e425306aSStefan Hajnoczi 478e425306aSStefan Hajnoczi self.cancel_and_wait() 479e425306aSStefan Hajnoczi 480e425306aSStefan Hajnoczi def test_set_speed_invalid(self): 481ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 482e425306aSStefan Hajnoczi 483e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=-1) 48458c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 485e425306aSStefan Hajnoczi 486ecc1c88eSStefan Hajnoczi self.assert_no_active_block_jobs() 487e425306aSStefan Hajnoczi 488e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 489e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 490e425306aSStefan Hajnoczi 491e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 49258c8cce2SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 493e425306aSStefan Hajnoczi 494e425306aSStefan Hajnoczi self.cancel_and_wait() 495e425306aSStefan Hajnoczi 49637ce63ebSStefan Hajnocziif __name__ == '__main__': 49737ce63ebSStefan Hajnoczi iotests.main(supported_fmts=['qcow2', 'qed']) 498