|
|
1.1 ! root 1: #!/usr/bin/env python ! 2: # ! 3: # Tests for image streaming. ! 4: # ! 5: # Copyright (C) 2012 IBM Corp. ! 6: # ! 7: # This program is free software; you can redistribute it and/or modify ! 8: # it under the terms of the GNU General Public License as published by ! 9: # the Free Software Foundation; either version 2 of the License, or ! 10: # (at your option) any later version. ! 11: # ! 12: # This program is distributed in the hope that it will be useful, ! 13: # but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: # GNU General Public License for more details. ! 16: # ! 17: # You should have received a copy of the GNU General Public License ! 18: # along with this program. If not, see <http://www.gnu.org/licenses/>. ! 19: # ! 20: ! 21: import os ! 22: import iotests ! 23: from iotests import qemu_img, qemu_io ! 24: ! 25: backing_img = os.path.join(iotests.test_dir, 'backing.img') ! 26: mid_img = os.path.join(iotests.test_dir, 'mid.img') ! 27: test_img = os.path.join(iotests.test_dir, 'test.img') ! 28: ! 29: class ImageStreamingTestCase(iotests.QMPTestCase): ! 30: '''Abstract base class for image streaming test cases''' ! 31: ! 32: def assert_no_active_streams(self): ! 33: result = self.vm.qmp('query-block-jobs') ! 34: self.assert_qmp(result, 'return', []) ! 35: ! 36: def cancel_and_wait(self, drive='drive0'): ! 37: '''Cancel a block job and wait for it to finish''' ! 38: result = self.vm.qmp('block-job-cancel', device=drive) ! 39: self.assert_qmp(result, 'return', {}) ! 40: ! 41: cancelled = False ! 42: while not cancelled: ! 43: for event in self.vm.get_qmp_events(wait=True): ! 44: if event['event'] == 'BLOCK_JOB_CANCELLED': ! 45: self.assert_qmp(event, 'data/type', 'stream') ! 46: self.assert_qmp(event, 'data/device', drive) ! 47: cancelled = True ! 48: ! 49: self.assert_no_active_streams() ! 50: ! 51: class TestSingleDrive(ImageStreamingTestCase): ! 52: image_len = 1 * 1024 * 1024 # MB ! 53: ! 54: def setUp(self): ! 55: qemu_img('create', backing_img, str(TestSingleDrive.image_len)) ! 56: qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) ! 57: qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) ! 58: self.vm = iotests.VM().add_drive(test_img) ! 59: self.vm.launch() ! 60: ! 61: def tearDown(self): ! 62: self.vm.shutdown() ! 63: os.remove(test_img) ! 64: os.remove(mid_img) ! 65: os.remove(backing_img) ! 66: ! 67: def test_stream(self): ! 68: self.assert_no_active_streams() ! 69: ! 70: result = self.vm.qmp('block-stream', device='drive0') ! 71: self.assert_qmp(result, 'return', {}) ! 72: ! 73: completed = False ! 74: while not completed: ! 75: for event in self.vm.get_qmp_events(wait=True): ! 76: if event['event'] == 'BLOCK_JOB_COMPLETED': ! 77: self.assert_qmp(event, 'data/type', 'stream') ! 78: self.assert_qmp(event, 'data/device', 'drive0') ! 79: self.assert_qmp(event, 'data/offset', self.image_len) ! 80: self.assert_qmp(event, 'data/len', self.image_len) ! 81: completed = True ! 82: ! 83: self.assert_no_active_streams() ! 84: self.vm.shutdown() ! 85: ! 86: self.assertEqual(qemu_io('-c', 'map', backing_img), ! 87: qemu_io('-c', 'map', test_img), ! 88: 'image file map does not match backing file after streaming') ! 89: ! 90: def test_stream_partial(self): ! 91: self.assert_no_active_streams() ! 92: ! 93: result = self.vm.qmp('block-stream', device='drive0', base=mid_img) ! 94: self.assert_qmp(result, 'return', {}) ! 95: ! 96: completed = False ! 97: while not completed: ! 98: for event in self.vm.get_qmp_events(wait=True): ! 99: if event['event'] == 'BLOCK_JOB_COMPLETED': ! 100: self.assert_qmp(event, 'data/type', 'stream') ! 101: self.assert_qmp(event, 'data/device', 'drive0') ! 102: self.assert_qmp(event, 'data/offset', self.image_len) ! 103: self.assert_qmp(event, 'data/len', self.image_len) ! 104: completed = True ! 105: ! 106: self.assert_no_active_streams() ! 107: self.vm.shutdown() ! 108: ! 109: self.assertEqual(qemu_io('-c', 'map', mid_img), ! 110: qemu_io('-c', 'map', test_img), ! 111: 'image file map does not match backing file after streaming') ! 112: ! 113: def test_device_not_found(self): ! 114: result = self.vm.qmp('block-stream', device='nonexistent') ! 115: self.assert_qmp(result, 'error/class', 'DeviceNotFound') ! 116: ! 117: class TestStreamStop(ImageStreamingTestCase): ! 118: image_len = 8 * 1024 * 1024 * 1024 # GB ! 119: ! 120: def setUp(self): ! 121: qemu_img('create', backing_img, str(TestStreamStop.image_len)) ! 122: qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) ! 123: self.vm = iotests.VM().add_drive(test_img) ! 124: self.vm.launch() ! 125: ! 126: def tearDown(self): ! 127: self.vm.shutdown() ! 128: os.remove(test_img) ! 129: os.remove(backing_img) ! 130: ! 131: def test_stream_stop(self): ! 132: import time ! 133: ! 134: self.assert_no_active_streams() ! 135: ! 136: result = self.vm.qmp('block-stream', device='drive0') ! 137: self.assert_qmp(result, 'return', {}) ! 138: ! 139: time.sleep(1) ! 140: events = self.vm.get_qmp_events(wait=False) ! 141: self.assertEqual(events, [], 'unexpected QMP event: %s' % events) ! 142: ! 143: self.cancel_and_wait() ! 144: ! 145: class TestSetSpeed(ImageStreamingTestCase): ! 146: image_len = 80 * 1024 * 1024 # MB ! 147: ! 148: def setUp(self): ! 149: qemu_img('create', backing_img, str(TestSetSpeed.image_len)) ! 150: qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) ! 151: self.vm = iotests.VM().add_drive(test_img) ! 152: self.vm.launch() ! 153: ! 154: def tearDown(self): ! 155: self.vm.shutdown() ! 156: os.remove(test_img) ! 157: os.remove(backing_img) ! 158: ! 159: # This is a short performance test which is not run by default. ! 160: # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput" ! 161: def perf_test_throughput(self): ! 162: self.assert_no_active_streams() ! 163: ! 164: result = self.vm.qmp('block-stream', device='drive0') ! 165: self.assert_qmp(result, 'return', {}) ! 166: ! 167: result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) ! 168: self.assert_qmp(result, 'return', {}) ! 169: ! 170: completed = False ! 171: while not completed: ! 172: for event in self.vm.get_qmp_events(wait=True): ! 173: if event['event'] == 'BLOCK_JOB_COMPLETED': ! 174: self.assert_qmp(event, 'data/type', 'stream') ! 175: self.assert_qmp(event, 'data/device', 'drive0') ! 176: self.assert_qmp(event, 'data/offset', self.image_len) ! 177: self.assert_qmp(event, 'data/len', self.image_len) ! 178: completed = True ! 179: ! 180: self.assert_no_active_streams() ! 181: ! 182: def test_set_speed(self): ! 183: self.assert_no_active_streams() ! 184: ! 185: result = self.vm.qmp('block-stream', device='drive0') ! 186: self.assert_qmp(result, 'return', {}) ! 187: ! 188: # Default speed is 0 ! 189: result = self.vm.qmp('query-block-jobs') ! 190: self.assert_qmp(result, 'return[0]/device', 'drive0') ! 191: self.assert_qmp(result, 'return[0]/speed', 0) ! 192: ! 193: result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) ! 194: self.assert_qmp(result, 'return', {}) ! 195: ! 196: # Ensure the speed we set was accepted ! 197: result = self.vm.qmp('query-block-jobs') ! 198: self.assert_qmp(result, 'return[0]/device', 'drive0') ! 199: self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) ! 200: ! 201: self.cancel_and_wait() ! 202: ! 203: # Check setting speed in block-stream works ! 204: result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024) ! 205: self.assert_qmp(result, 'return', {}) ! 206: ! 207: result = self.vm.qmp('query-block-jobs') ! 208: self.assert_qmp(result, 'return[0]/device', 'drive0') ! 209: self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) ! 210: ! 211: self.cancel_and_wait() ! 212: ! 213: def test_set_speed_invalid(self): ! 214: self.assert_no_active_streams() ! 215: ! 216: result = self.vm.qmp('block-stream', device='drive0', speed=-1) ! 217: self.assert_qmp(result, 'error/class', 'InvalidParameter') ! 218: self.assert_qmp(result, 'error/data/name', 'speed') ! 219: ! 220: self.assert_no_active_streams() ! 221: ! 222: result = self.vm.qmp('block-stream', device='drive0') ! 223: self.assert_qmp(result, 'return', {}) ! 224: ! 225: result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) ! 226: self.assert_qmp(result, 'error/class', 'InvalidParameter') ! 227: self.assert_qmp(result, 'error/data/name', 'speed') ! 228: ! 229: self.cancel_and_wait() ! 230: ! 231: if __name__ == '__main__': ! 232: iotests.main(supported_fmts=['qcow2', 'qed'])
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.