xref: /openbmc/qemu/tests/qemu-iotests/030 (revision 774a8850d708aeb6dd6de493c28b374098c1a4c3)
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
128*774a8850SStefan Hajnoczi
129*774a8850SStefan Hajnocziclass TestSmallerBackingFile(ImageStreamingTestCase):
130*774a8850SStefan Hajnoczi    backing_len = 1 * 1024 * 1024 # MB
131*774a8850SStefan Hajnoczi    image_len = 2 * backing_len
132*774a8850SStefan Hajnoczi
133*774a8850SStefan Hajnoczi    def setUp(self):
134*774a8850SStefan Hajnoczi        self.create_image(backing_img, self.backing_len)
135*774a8850SStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
136*774a8850SStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
137*774a8850SStefan Hajnoczi        self.vm.launch()
138*774a8850SStefan Hajnoczi
139*774a8850SStefan Hajnoczi    # If this hangs, then you are missing a fix to complete streaming when the
140*774a8850SStefan Hajnoczi    # end of the backing file is reached.
141*774a8850SStefan Hajnoczi    def test_stream(self):
142*774a8850SStefan Hajnoczi        self.assert_no_active_streams()
143*774a8850SStefan Hajnoczi
144*774a8850SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
145*774a8850SStefan Hajnoczi        self.assert_qmp(result, 'return', {})
146*774a8850SStefan Hajnoczi
147*774a8850SStefan Hajnoczi        completed = False
148*774a8850SStefan Hajnoczi        while not completed:
149*774a8850SStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
150*774a8850SStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
151*774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
152*774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
153*774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
154*774a8850SStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
155*774a8850SStefan Hajnoczi                    completed = True
156*774a8850SStefan Hajnoczi
157*774a8850SStefan Hajnoczi        self.assert_no_active_streams()
158*774a8850SStefan Hajnoczi        self.vm.shutdown()
159*774a8850SStefan Hajnoczi
160*774a8850SStefan Hajnoczi
16137ce63ebSStefan Hajnocziclass TestStreamStop(ImageStreamingTestCase):
16237ce63ebSStefan Hajnoczi    image_len = 8 * 1024 * 1024 * 1024 # GB
16337ce63ebSStefan Hajnoczi
16437ce63ebSStefan Hajnoczi    def setUp(self):
16537ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestStreamStop.image_len))
16637ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
16737ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
16837ce63ebSStefan Hajnoczi        self.vm.launch()
16937ce63ebSStefan Hajnoczi
17037ce63ebSStefan Hajnoczi    def tearDown(self):
17137ce63ebSStefan Hajnoczi        self.vm.shutdown()
17237ce63ebSStefan Hajnoczi        os.remove(test_img)
17337ce63ebSStefan Hajnoczi        os.remove(backing_img)
17437ce63ebSStefan Hajnoczi
17537ce63ebSStefan Hajnoczi    def test_stream_stop(self):
17637ce63ebSStefan Hajnoczi        import time
17737ce63ebSStefan Hajnoczi
17837ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
17937ce63ebSStefan Hajnoczi
180db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
18137ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
18237ce63ebSStefan Hajnoczi
1830fd05e8dSPaolo Bonzini        time.sleep(0.1)
18437ce63ebSStefan Hajnoczi        events = self.vm.get_qmp_events(wait=False)
18537ce63ebSStefan Hajnoczi        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
18637ce63ebSStefan Hajnoczi
187e425306aSStefan Hajnoczi        self.cancel_and_wait()
18837ce63ebSStefan Hajnoczi
18937ce63ebSStefan Hajnocziclass TestSetSpeed(ImageStreamingTestCase):
19037ce63ebSStefan Hajnoczi    image_len = 80 * 1024 * 1024 # MB
19137ce63ebSStefan Hajnoczi
19237ce63ebSStefan Hajnoczi    def setUp(self):
19337ce63ebSStefan Hajnoczi        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
19437ce63ebSStefan Hajnoczi        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
19537ce63ebSStefan Hajnoczi        self.vm = iotests.VM().add_drive(test_img)
19637ce63ebSStefan Hajnoczi        self.vm.launch()
19737ce63ebSStefan Hajnoczi
19837ce63ebSStefan Hajnoczi    def tearDown(self):
19937ce63ebSStefan Hajnoczi        self.vm.shutdown()
20037ce63ebSStefan Hajnoczi        os.remove(test_img)
20137ce63ebSStefan Hajnoczi        os.remove(backing_img)
20237ce63ebSStefan Hajnoczi
203e425306aSStefan Hajnoczi    # This is a short performance test which is not run by default.
204e425306aSStefan Hajnoczi    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
205e425306aSStefan Hajnoczi    def perf_test_throughput(self):
20637ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
20737ce63ebSStefan Hajnoczi
208db58f9c0SStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
20937ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
21037ce63ebSStefan Hajnoczi
211e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
21237ce63ebSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
21337ce63ebSStefan Hajnoczi
21437ce63ebSStefan Hajnoczi        completed = False
21537ce63ebSStefan Hajnoczi        while not completed:
21637ce63ebSStefan Hajnoczi            for event in self.vm.get_qmp_events(wait=True):
21737ce63ebSStefan Hajnoczi                if event['event'] == 'BLOCK_JOB_COMPLETED':
21837ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/type', 'stream')
21937ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/device', 'drive0')
22037ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/offset', self.image_len)
22137ce63ebSStefan Hajnoczi                    self.assert_qmp(event, 'data/len', self.image_len)
22237ce63ebSStefan Hajnoczi                    completed = True
22337ce63ebSStefan Hajnoczi
22437ce63ebSStefan Hajnoczi        self.assert_no_active_streams()
22537ce63ebSStefan Hajnoczi
226e425306aSStefan Hajnoczi    def test_set_speed(self):
227e425306aSStefan Hajnoczi        self.assert_no_active_streams()
228e425306aSStefan Hajnoczi
229e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
230e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
231e425306aSStefan Hajnoczi
232e425306aSStefan Hajnoczi        # Default speed is 0
233e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
234e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
235e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 0)
236e425306aSStefan Hajnoczi
237e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
238e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
239e425306aSStefan Hajnoczi
240e425306aSStefan Hajnoczi        # Ensure the speed we set was accepted
241e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
242e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
243e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
244e425306aSStefan Hajnoczi
245e425306aSStefan Hajnoczi        self.cancel_and_wait()
246e425306aSStefan Hajnoczi
247e425306aSStefan Hajnoczi        # Check setting speed in block-stream works
248e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
249e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
250e425306aSStefan Hajnoczi
251e425306aSStefan Hajnoczi        result = self.vm.qmp('query-block-jobs')
252e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/device', 'drive0')
253e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
254e425306aSStefan Hajnoczi
255e425306aSStefan Hajnoczi        self.cancel_and_wait()
256e425306aSStefan Hajnoczi
257e425306aSStefan Hajnoczi    def test_set_speed_invalid(self):
258e425306aSStefan Hajnoczi        self.assert_no_active_streams()
259e425306aSStefan Hajnoczi
260e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
26158c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
262e425306aSStefan Hajnoczi
263e425306aSStefan Hajnoczi        self.assert_no_active_streams()
264e425306aSStefan Hajnoczi
265e425306aSStefan Hajnoczi        result = self.vm.qmp('block-stream', device='drive0')
266e425306aSStefan Hajnoczi        self.assert_qmp(result, 'return', {})
267e425306aSStefan Hajnoczi
268e425306aSStefan Hajnoczi        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
26958c8cce2SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
270e425306aSStefan Hajnoczi
271e425306aSStefan Hajnoczi        self.cancel_and_wait()
272e425306aSStefan Hajnoczi
27337ce63ebSStefan Hajnocziif __name__ == '__main__':
27437ce63ebSStefan Hajnoczi    iotests.main(supported_fmts=['qcow2', 'qed'])
275