xref: /qemu/tests/qemu-iotests/030 (revision 6e343609)
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')
26*6e343609SPaolo Bonzinimid_img = os.path.join(iotests.test_dir, 'mid.img')
2737ce63ebSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img')
2837ce63ebSStefan Hajnoczi
2937ce63ebSStefan Hajnocziclass ImageStreamingTestCase(iotests.QMPTestCase):
3037ce63ebSStefan Hajnoczi    '''Abstract base class for image streaming test cases'''
3137ce63ebSStefan Hajnoczi
3237ce63ebSStefan Hajnoczi    def assert_no_active_streams(self):
3337ce63ebSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
3437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', [])
3537ce63ebSStefan Hajnoczi
36e425306aSStefan Hajnoczi    def cancel_and_wait(self, drive='drive0'):
37e425306aSStefan Hajnoczi        '''Cancel a block job and wait for it to finish'''
38e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-cancel', device=drive)
39e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
40e425306aSStefan Hajnoczi
41e425306aSStefan Hajnoczi        cancelled = False
42e425306aSStefan Hajnoczi        while not cancelled:
43e425306aSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
44e425306aSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_CANCELLED':
45e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
46e425306aSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', drive)
47e425306aSStefan Hajnoczi                    cancelled = True
48e425306aSStefan Hajnoczi
49e425306aSStefan Hajnoczi        self.assert_no_active_streams()
50e425306aSStefan Hajnoczi
5137ce63ebSStefan Hajnocziclass TestSingleDrive(ImageStreamingTestCase):
5237ce63ebSStefan Hajnoczi    image_len = 1 * 1024 * 1024 # MB
5337ce63ebSStefan Hajnoczi
5437ce63ebSStefan Hajnoczi    def setUp(self):
5537ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSingleDrive.image_len))
56*6e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
57*6e343609SPaolo Bonzini        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
5837ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
5937ce63ebSStefan Hajnoczi        self.vm.launch()
6037ce63ebSStefan Hajnoczi
6137ce63ebSStefan Hajnoczi    def tearDown(self):
6237ce63ebSStefan Hajnoczi        self.vm.shutdown()
6337ce63ebSStefan Hajnoczi        os.remove(test_img)
64*6e343609SPaolo Bonzini        os.remove(mid_img)
6537ce63ebSStefan Hajnoczi        os.remove(backing_img)
6637ce63ebSStefan Hajnoczi
6737ce63ebSStefan Hajnoczi    def test_stream(self):
6837ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
6937ce63ebSStefan Hajnoczi
70db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
7137ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
7237ce63ebSStefan Hajnoczi
7337ce63ebSStefan Hajnoczi        completed = False
7437ce63ebSStefan Hajnoczi        while not completed:
7537ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
7637ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
7737ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
7837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
7937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
8037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
8137ce63ebSStefan Hajnoczi                    completed = True
8237ce63ebSStefan Hajnoczi
8337ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
84863a5d04SPaolo Bonzini        self.vm.shutdown()
8537ce63ebSStefan Hajnoczi
8637ce63ebSStefan Hajnoczi        self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', test_img),
8737ce63ebSStefan Hajnoczi                         'image file not fully populated after streaming')
8837ce63ebSStefan Hajnoczi
89*6e343609SPaolo Bonzini    def test_stream_partial(self):
90*6e343609SPaolo Bonzini        self.assert_no_active_streams()
91*6e343609SPaolo Bonzini
92*6e343609SPaolo Bonzini        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
93*6e343609SPaolo Bonzini        self.assert_qmp(result, 'return', {})
94*6e343609SPaolo Bonzini
95*6e343609SPaolo Bonzini        completed = False
96*6e343609SPaolo Bonzini        while not completed:
97*6e343609SPaolo Bonzini            for event in self.vm.get_qmp_events(wait=True):
98*6e343609SPaolo Bonzini                if event['event'] == 'BLOCK_JOB_COMPLETED':
99*6e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/type', 'stream')
100*6e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/device', 'drive0')
101*6e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/offset', self.image_len)
102*6e343609SPaolo Bonzini                    self.assert_qmp(event, 'data/len', self.image_len)
103*6e343609SPaolo Bonzini                    completed = True
104*6e343609SPaolo Bonzini
105*6e343609SPaolo Bonzini        self.assert_no_active_streams()
106*6e343609SPaolo Bonzini        self.vm.shutdown()
107*6e343609SPaolo Bonzini
108*6e343609SPaolo Bonzini        self.assertEqual(qemu_io('-c', 'map', mid_img),
109*6e343609SPaolo Bonzini                         qemu_io('-c', 'map', test_img),
110*6e343609SPaolo Bonzini                         'image file map does not match backing file after streaming')
111*6e343609SPaolo Bonzini
11237ce63ebSStefan Hajnoczi    def test_device_not_found(self):
113db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='nonexistent')
11437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
11537ce63ebSStefan Hajnoczi
11637ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase):
11737ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
11837ce63ebSStefan Hajnoczi
11937ce63ebSStefan Hajnoczi    def setUp(self):
12037ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
12137ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
12237ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
12337ce63ebSStefan Hajnoczi        self.vm.launch()
12437ce63ebSStefan Hajnoczi
12537ce63ebSStefan Hajnoczi    def tearDown(self):
12637ce63ebSStefan Hajnoczi        self.vm.shutdown()
12737ce63ebSStefan Hajnoczi        os.remove(test_img)
12837ce63ebSStefan Hajnoczi        os.remove(backing_img)
12937ce63ebSStefan Hajnoczi
13037ce63ebSStefan Hajnoczi    def test_stream_stop(self):
13137ce63ebSStefan Hajnoczi        import time
13237ce63ebSStefan Hajnoczi
13337ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
13437ce63ebSStefan Hajnoczi
135db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
13637ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
13737ce63ebSStefan Hajnoczi
13837ce63ebSStefan Hajnoczi        time.sleep(1)
13937ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
14037ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
14137ce63ebSStefan Hajnoczi
142e425306aSStefan Hajnoczi        self.cancel_and_wait()
14337ce63ebSStefan Hajnoczi
14437ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase):
14537ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
14637ce63ebSStefan Hajnoczi
14737ce63ebSStefan Hajnoczi    def setUp(self):
14837ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
14937ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
15037ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
15137ce63ebSStefan Hajnoczi        self.vm.launch()
15237ce63ebSStefan Hajnoczi
15337ce63ebSStefan Hajnoczi    def tearDown(self):
15437ce63ebSStefan Hajnoczi        self.vm.shutdown()
15537ce63ebSStefan Hajnoczi        os.remove(test_img)
15637ce63ebSStefan Hajnoczi        os.remove(backing_img)
15737ce63ebSStefan Hajnoczi
158e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
159e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
160e425306aSStefan Hajnoczi    def perf_test_throughput(self):
16137ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
16237ce63ebSStefan Hajnoczi
163db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
16437ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
16537ce63ebSStefan Hajnoczi
166e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
16737ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
16837ce63ebSStefan Hajnoczi
16937ce63ebSStefan Hajnoczi        completed = False
17037ce63ebSStefan Hajnoczi        while not completed:
17137ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
17237ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
17337ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
17437ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
17537ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
17637ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
17737ce63ebSStefan Hajnoczi                    completed = True
17837ce63ebSStefan Hajnoczi
17937ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
18037ce63ebSStefan Hajnoczi
181e425306aSStefan Hajnoczi    def test_set_speed(self):
182e425306aSStefan Hajnoczi        self.assert_no_active_streams()
183e425306aSStefan Hajnoczi
184e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
185e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
186e425306aSStefan Hajnoczi
187e425306aSStefan Hajnoczi        # Default speed is 0
188e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
189e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
190e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
191e425306aSStefan Hajnoczi
192e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
193e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
194e425306aSStefan Hajnoczi
195e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
196e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
197e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
198e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
199e425306aSStefan Hajnoczi
200e425306aSStefan Hajnoczi        self.cancel_and_wait()
201e425306aSStefan Hajnoczi
202e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
203e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
204e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
205e425306aSStefan Hajnoczi
206e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
207e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
208e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
209e425306aSStefan Hajnoczi
210e425306aSStefan Hajnoczi        self.cancel_and_wait()
211e425306aSStefan Hajnoczi
212e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
213e425306aSStefan Hajnoczi        self.assert_no_active_streams()
214e425306aSStefan Hajnoczi
215e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
216e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'InvalidParameter')
217e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/data/name', 'speed')
218e425306aSStefan Hajnoczi
219e425306aSStefan Hajnoczi        self.assert_no_active_streams()
220e425306aSStefan Hajnoczi
221e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
222e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
223e425306aSStefan Hajnoczi
224e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
225e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/class', 'InvalidParameter')
226e425306aSStefan Hajnoczi        self.assert_qmp(result, 'error/data/name', 'speed')
227e425306aSStefan Hajnoczi
228e425306aSStefan Hajnoczi        self.cancel_and_wait()
229e425306aSStefan Hajnoczi
23037ce63ebSStefan Hajnocziif __name__ == '__main__':
23137ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
232