xref: /qemu/tests/qemu-iotests/030 (revision 0fd05e8d)
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
24ab68cdfaSPaolo Bonziniimport struct
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
3037ce63ebSStefan Hajnocziclass ImageStreamingTestCase(iotests.QMPTestCase):
3137ce63ebSStefan Hajnoczi    '''Abstract base class for image streaming test cases'''
3237ce63ebSStefan Hajnoczi
3337ce63ebSStefan Hajnoczi    def assert_no_active_streams(self):
3437ce63ebSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
3537ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', [])
3637ce63ebSStefan Hajnoczi
37e425306aSStefan Hajnoczi    def cancel_and_wait(self, drive='drive0'):
38e425306aSStefan Hajnoczi        '''Cancel a block job and wait for it to finish'''
39e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-cancel', device=drive)
40e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
41e425306aSStefan Hajnoczi
42e425306aSStefan Hajnoczi        cancelled = False
43e425306aSStefan Hajnoczi        while not cancelled:
44e425306aSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
45e425306aSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_CANCELLED':
46e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
47e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', drive)
48e425306aSStefan Hajnoczi                    cancelled = True
49e425306aSStefan Hajnoczi
50e425306aSStefan Hajnoczi        self.assert_no_active_streams()
51e425306aSStefan Hajnoczi
52ab68cdfaSPaolo Bonzini    def create_image(self, name, size):
53ab68cdfaSPaolo Bonzini        file = open(name, 'w')
54ab68cdfaSPaolo Bonzini        i = 0
55ab68cdfaSPaolo Bonzini        while i < size:
56ab68cdfaSPaolo Bonzini            sector = struct.pack('>l504xl', i / 512, i / 512)
57ab68cdfaSPaolo Bonzini            file.write(sector)
58ab68cdfaSPaolo Bonzini            i = i + 512
59ab68cdfaSPaolo Bonzini        file.close()
60ab68cdfaSPaolo Bonzini
61ab68cdfaSPaolo Bonzini
6237ce63ebSStefan Hajnocziclass TestSingleDrive(ImageStreamingTestCase):
6337ce63ebSStefan Hajnoczi    image_len = 1 * 1024 * 1024 # MB
6437ce63ebSStefan Hajnoczi
6537ce63ebSStefan Hajnoczi    def setUp(self):
66ab68cdfaSPaolo Bonzini        self.create_image(backing_img, TestSingleDrive.image_len)
676e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
686e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
6937ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
7037ce63ebSStefan Hajnoczi        self.vm.launch()
7137ce63ebSStefan Hajnoczi
7237ce63ebSStefan Hajnoczi    def tearDown(self):
7337ce63ebSStefan Hajnoczi        self.vm.shutdown()
7437ce63ebSStefan Hajnoczi        os.remove(test_img)
756e343609SPaolo Bonzini        os.remove(mid_img)
7637ce63ebSStefan Hajnoczi        os.remove(backing_img)
7737ce63ebSStefan Hajnoczi
7837ce63ebSStefan Hajnoczi    def test_stream(self):
7937ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
8037ce63ebSStefan Hajnoczi
81db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
8237ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
8337ce63ebSStefan Hajnoczi
8437ce63ebSStefan Hajnoczi        completed = False
8537ce63ebSStefan Hajnoczi        while not completed:
8637ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
8737ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
8837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
8937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
9037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
9137ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
9237ce63ebSStefan Hajnoczi                    completed = True
9337ce63ebSStefan Hajnoczi
9437ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
95863a5d04SPaolo Bonzini        self.vm.shutdown()
9637ce63ebSStefan Hajnoczi
97efcc7a23SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', backing_img),
98efcc7a23SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
99efcc7a23SPaolo Bonzini                         'image file map does not match backing file after streaming')
10037ce63ebSStefan Hajnoczi
1016e343609SPaolo Bonzini    def test_stream_partial(self):
1026e343609SPaolo Bonzini        self.assert_no_active_streams()
1036e343609SPaolo Bonzini
1046e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
1056e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
1066e343609SPaolo Bonzini
1076e343609SPaolo Bonzini        completed = False
1086e343609SPaolo Bonzini        while not completed:
1096e343609SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
1106e343609SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
1116e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
1126e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
1136e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
1146e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
1156e343609SPaolo Bonzini                    completed = True
1166e343609SPaolo Bonzini
1176e343609SPaolo Bonzini        self.assert_no_active_streams()
1186e343609SPaolo Bonzini        self.vm.shutdown()
1196e343609SPaolo Bonzini
1206e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
1216e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
1226e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
1236e343609SPaolo Bonzini
12437ce63ebSStefan Hajnoczi    def test_device_not_found(self):
125db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
12637ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
12737ce63ebSStefan Hajnoczi
12837ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase):
12937ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
13037ce63ebSStefan Hajnoczi
13137ce63ebSStefan Hajnoczi    def setUp(self):
13237ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
13337ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
13437ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
13537ce63ebSStefan Hajnoczi        self.vm.launch()
13637ce63ebSStefan Hajnoczi
13737ce63ebSStefan Hajnoczi    def tearDown(self):
13837ce63ebSStefan Hajnoczi        self.vm.shutdown()
13937ce63ebSStefan Hajnoczi        os.remove(test_img)
14037ce63ebSStefan Hajnoczi        os.remove(backing_img)
14137ce63ebSStefan Hajnoczi
14237ce63ebSStefan Hajnoczi    def test_stream_stop(self):
14337ce63ebSStefan Hajnoczi        import time
14437ce63ebSStefan Hajnoczi
14537ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
14637ce63ebSStefan Hajnoczi
147db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
14837ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
14937ce63ebSStefan Hajnoczi
150*0fd05e8dSPaolo Bonzini        time.sleep(0.1)
15137ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
15237ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
15337ce63ebSStefan Hajnoczi
154e425306aSStefan Hajnoczi        self.cancel_and_wait()
15537ce63ebSStefan Hajnoczi
15637ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase):
15737ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
15837ce63ebSStefan Hajnoczi
15937ce63ebSStefan Hajnoczi    def setUp(self):
16037ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
16137ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
16237ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
16337ce63ebSStefan Hajnoczi        self.vm.launch()
16437ce63ebSStefan Hajnoczi
16537ce63ebSStefan Hajnoczi    def tearDown(self):
16637ce63ebSStefan Hajnoczi        self.vm.shutdown()
16737ce63ebSStefan Hajnoczi        os.remove(test_img)
16837ce63ebSStefan Hajnoczi        os.remove(backing_img)
16937ce63ebSStefan Hajnoczi
170e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
171e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
172e425306aSStefan Hajnoczi    def perf_test_throughput(self):
17337ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
17437ce63ebSStefan Hajnoczi
175db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
17637ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
17737ce63ebSStefan Hajnoczi
178e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
17937ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
18037ce63ebSStefan Hajnoczi
18137ce63ebSStefan Hajnoczi        completed = False
18237ce63ebSStefan Hajnoczi        while not completed:
18337ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
18437ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
18537ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
18637ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
18737ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
18837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
18937ce63ebSStefan Hajnoczi                    completed = True
19037ce63ebSStefan Hajnoczi
19137ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
19237ce63ebSStefan Hajnoczi
193e425306aSStefan Hajnoczi    def test_set_speed(self):
194e425306aSStefan Hajnoczi        self.assert_no_active_streams()
195e425306aSStefan Hajnoczi
196e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
197e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
198e425306aSStefan Hajnoczi
199e425306aSStefan Hajnoczi        # Default speed is 0
200e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
201e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
202e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
203e425306aSStefan Hajnoczi
204e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
205e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
206e425306aSStefan Hajnoczi
207e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
208e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
209e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
210e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
211e425306aSStefan Hajnoczi
212e425306aSStefan Hajnoczi        self.cancel_and_wait()
213e425306aSStefan Hajnoczi
214e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
215e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
216e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
217e425306aSStefan Hajnoczi
218e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
219e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
220e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
221e425306aSStefan Hajnoczi
222e425306aSStefan Hajnoczi        self.cancel_and_wait()
223e425306aSStefan Hajnoczi
224e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
225e425306aSStefan Hajnoczi        self.assert_no_active_streams()
226e425306aSStefan Hajnoczi
227e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
228e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'InvalidParameter')
229e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/data/name', 'speed')
230e425306aSStefan Hajnoczi
231e425306aSStefan Hajnoczi        self.assert_no_active_streams()
232e425306aSStefan Hajnoczi
233e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
234e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
235e425306aSStefan Hajnoczi
236e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
237e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'InvalidParameter')
238e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/data/name', 'speed')
239e425306aSStefan Hajnoczi
240e425306aSStefan Hajnoczi        self.cancel_and_wait()
241e425306aSStefan Hajnoczi
24237ce63ebSStefan Hajnocziif __name__ == '__main__':
24337ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
244