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 2137ce63ebSStefan Hajnocziimport os 2237ce63ebSStefan Hajnocziimport iotests 2337ce63ebSStefan Hajnoczifrom iotests import qemu_img, qemu_io 2437ce63ebSStefan Hajnoczi 2537ce63ebSStefan Hajnoczibacking_img = os.path.join(iotests.test_dir, 'backing.img') 2637ce63ebSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img') 2737ce63ebSStefan Hajnoczi 2837ce63ebSStefan Hajnocziclass ImageStreamingTestCase(iotests.QMPTestCase): 2937ce63ebSStefan Hajnoczi '''Abstract base class for image streaming test cases''' 3037ce63ebSStefan Hajnoczi 3137ce63ebSStefan Hajnoczi def assert_no_active_streams(self): 3237ce63ebSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 3337ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', []) 3437ce63ebSStefan Hajnoczi 35e425306aSStefan Hajnoczi def cancel_and_wait(self, drive='drive0'): 36e425306aSStefan Hajnoczi '''Cancel a block job and wait for it to finish''' 37e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-cancel', device=drive) 38e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 39e425306aSStefan Hajnoczi 40e425306aSStefan Hajnoczi cancelled = False 41e425306aSStefan Hajnoczi while not cancelled: 42e425306aSStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 43e425306aSStefan Hajnoczi if event['event'] == 'BLOCK_JOB_CANCELLED': 44e425306aSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 45e425306aSStefan Hajnoczi self.assert_qmp(event, 'data/device', drive) 46e425306aSStefan Hajnoczi cancelled = True 47e425306aSStefan Hajnoczi 48e425306aSStefan Hajnoczi self.assert_no_active_streams() 49e425306aSStefan Hajnoczi 5037ce63ebSStefan Hajnocziclass TestSingleDrive(ImageStreamingTestCase): 5137ce63ebSStefan Hajnoczi image_len = 1 * 1024 * 1024 # MB 5237ce63ebSStefan Hajnoczi 5337ce63ebSStefan Hajnoczi def setUp(self): 5437ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestSingleDrive.image_len)) 5537ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 5637ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 5737ce63ebSStefan Hajnoczi self.vm.launch() 5837ce63ebSStefan Hajnoczi 5937ce63ebSStefan Hajnoczi def tearDown(self): 6037ce63ebSStefan Hajnoczi self.vm.shutdown() 6137ce63ebSStefan Hajnoczi os.remove(test_img) 6237ce63ebSStefan Hajnoczi os.remove(backing_img) 6337ce63ebSStefan Hajnoczi 6437ce63ebSStefan Hajnoczi def test_stream(self): 6537ce63ebSStefan Hajnoczi self.assert_no_active_streams() 6637ce63ebSStefan Hajnoczi 67db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 6837ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 6937ce63ebSStefan Hajnoczi 7037ce63ebSStefan Hajnoczi completed = False 7137ce63ebSStefan Hajnoczi while not completed: 7237ce63ebSStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 7337ce63ebSStefan Hajnoczi if event['event'] == 'BLOCK_JOB_COMPLETED': 7437ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 7537ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/device', 'drive0') 7637ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/offset', self.image_len) 7737ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/len', self.image_len) 7837ce63ebSStefan Hajnoczi completed = True 7937ce63ebSStefan Hajnoczi 8037ce63ebSStefan Hajnoczi self.assert_no_active_streams() 81*863a5d04SPaolo Bonzini self.vm.shutdown() 8237ce63ebSStefan Hajnoczi 8337ce63ebSStefan Hajnoczi self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', test_img), 8437ce63ebSStefan Hajnoczi 'image file not fully populated after streaming') 8537ce63ebSStefan Hajnoczi 8637ce63ebSStefan Hajnoczi def test_device_not_found(self): 87db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='nonexistent') 8837ce63ebSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'DeviceNotFound') 8937ce63ebSStefan Hajnoczi 9037ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase): 9137ce63ebSStefan Hajnoczi image_len = 8 * 1024 * 1024 * 1024 # GB 9237ce63ebSStefan Hajnoczi 9337ce63ebSStefan Hajnoczi def setUp(self): 9437ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestStreamStop.image_len)) 9537ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 9637ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 9737ce63ebSStefan Hajnoczi self.vm.launch() 9837ce63ebSStefan Hajnoczi 9937ce63ebSStefan Hajnoczi def tearDown(self): 10037ce63ebSStefan Hajnoczi self.vm.shutdown() 10137ce63ebSStefan Hajnoczi os.remove(test_img) 10237ce63ebSStefan Hajnoczi os.remove(backing_img) 10337ce63ebSStefan Hajnoczi 10437ce63ebSStefan Hajnoczi def test_stream_stop(self): 10537ce63ebSStefan Hajnoczi import time 10637ce63ebSStefan Hajnoczi 10737ce63ebSStefan Hajnoczi self.assert_no_active_streams() 10837ce63ebSStefan Hajnoczi 109db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 11037ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 11137ce63ebSStefan Hajnoczi 11237ce63ebSStefan Hajnoczi time.sleep(1) 11337ce63ebSStefan Hajnoczi events = self.vm.get_qmp_events(wait=False) 11437ce63ebSStefan Hajnoczi self.assertEqual(events, [], 'unexpected QMP event: %s' % events) 11537ce63ebSStefan Hajnoczi 116e425306aSStefan Hajnoczi self.cancel_and_wait() 11737ce63ebSStefan Hajnoczi 11837ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase): 11937ce63ebSStefan Hajnoczi image_len = 80 * 1024 * 1024 # MB 12037ce63ebSStefan Hajnoczi 12137ce63ebSStefan Hajnoczi def setUp(self): 12237ce63ebSStefan Hajnoczi qemu_img('create', backing_img, str(TestSetSpeed.image_len)) 12337ce63ebSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) 12437ce63ebSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 12537ce63ebSStefan Hajnoczi self.vm.launch() 12637ce63ebSStefan Hajnoczi 12737ce63ebSStefan Hajnoczi def tearDown(self): 12837ce63ebSStefan Hajnoczi self.vm.shutdown() 12937ce63ebSStefan Hajnoczi os.remove(test_img) 13037ce63ebSStefan Hajnoczi os.remove(backing_img) 13137ce63ebSStefan Hajnoczi 132e425306aSStefan Hajnoczi # This is a short performance test which is not run by default. 133e425306aSStefan Hajnoczi # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput" 134e425306aSStefan Hajnoczi def perf_test_throughput(self): 13537ce63ebSStefan Hajnoczi self.assert_no_active_streams() 13637ce63ebSStefan Hajnoczi 137db58f9c0SStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 13837ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 13937ce63ebSStefan Hajnoczi 140e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 14137ce63ebSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 14237ce63ebSStefan Hajnoczi 14337ce63ebSStefan Hajnoczi completed = False 14437ce63ebSStefan Hajnoczi while not completed: 14537ce63ebSStefan Hajnoczi for event in self.vm.get_qmp_events(wait=True): 14637ce63ebSStefan Hajnoczi if event['event'] == 'BLOCK_JOB_COMPLETED': 14737ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'stream') 14837ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/device', 'drive0') 14937ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/offset', self.image_len) 15037ce63ebSStefan Hajnoczi self.assert_qmp(event, 'data/len', self.image_len) 15137ce63ebSStefan Hajnoczi completed = True 15237ce63ebSStefan Hajnoczi 15337ce63ebSStefan Hajnoczi self.assert_no_active_streams() 15437ce63ebSStefan Hajnoczi 155e425306aSStefan Hajnoczi def test_set_speed(self): 156e425306aSStefan Hajnoczi self.assert_no_active_streams() 157e425306aSStefan Hajnoczi 158e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 159e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 160e425306aSStefan Hajnoczi 161e425306aSStefan Hajnoczi # Default speed is 0 162e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 163e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 164e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 165e425306aSStefan Hajnoczi 166e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 167e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 168e425306aSStefan Hajnoczi 169e425306aSStefan Hajnoczi # Ensure the speed we set was accepted 170e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 171e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 172e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 173e425306aSStefan Hajnoczi 174e425306aSStefan Hajnoczi self.cancel_and_wait() 175e425306aSStefan Hajnoczi 176e425306aSStefan Hajnoczi # Check setting speed in block-stream works 177e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024) 178e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 179e425306aSStefan Hajnoczi 180e425306aSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 181e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 182e425306aSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) 183e425306aSStefan Hajnoczi 184e425306aSStefan Hajnoczi self.cancel_and_wait() 185e425306aSStefan Hajnoczi 186e425306aSStefan Hajnoczi def test_set_speed_invalid(self): 187e425306aSStefan Hajnoczi self.assert_no_active_streams() 188e425306aSStefan Hajnoczi 189e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0', speed=-1) 190e425306aSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'InvalidParameter') 191e425306aSStefan Hajnoczi self.assert_qmp(result, 'error/data/name', 'speed') 192e425306aSStefan Hajnoczi 193e425306aSStefan Hajnoczi self.assert_no_active_streams() 194e425306aSStefan Hajnoczi 195e425306aSStefan Hajnoczi result = self.vm.qmp('block-stream', device='drive0') 196e425306aSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 197e425306aSStefan Hajnoczi 198e425306aSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 199e425306aSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'InvalidParameter') 200e425306aSStefan Hajnoczi self.assert_qmp(result, 'error/data/name', 'speed') 201e425306aSStefan Hajnoczi 202e425306aSStefan Hajnoczi self.cancel_and_wait() 203e425306aSStefan Hajnoczi 20437ce63ebSStefan Hajnocziif __name__ == '__main__': 20537ce63ebSStefan Hajnoczi iotests.main(supported_fmts=['qcow2', 'qed']) 206