block: in commit, determine base image from the top image
[qemu/kevin.git] / tests / qemu-iotests / 040
blob0fa6441a53e28f3f1f8c40c2ae89fe3d16193a11
1 #!/usr/bin/env python
3 # Tests for image block commit.
5 # Copyright (C) 2012 IBM, Corp.
6 # Copyright (C) 2012 Red Hat, Inc.
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # Test for live block commit
22 # Derived from Image Streaming Test 030
24 import time
25 import os
26 import iotests
27 from iotests import qemu_img, qemu_io
28 import struct
30 backing_img = os.path.join(iotests.test_dir, 'backing.img')
31 mid_img = os.path.join(iotests.test_dir, 'mid.img')
32 test_img = os.path.join(iotests.test_dir, 'test.img')
34 class ImageCommitTestCase(iotests.QMPTestCase):
35 '''Abstract base class for image commit test cases'''
37 def assert_no_active_commit(self):
38 result = self.vm.qmp('query-block-jobs')
39 self.assert_qmp(result, 'return', [])
41 def cancel_and_wait(self, drive='drive0'):
42 '''Cancel a block job and wait for it to finish'''
43 result = self.vm.qmp('block-job-cancel', device=drive)
44 self.assert_qmp(result, 'return', {})
46 cancelled = False
47 while not cancelled:
48 for event in self.vm.get_qmp_events(wait=True):
49 if event['event'] == 'BLOCK_JOB_CANCELLED':
50 self.assert_qmp(event, 'data/type', 'commit')
51 self.assert_qmp(event, 'data/device', drive)
52 cancelled = True
54 self.assert_no_active_commit()
56 def create_image(self, name, size):
57 file = open(name, 'w')
58 i = 0
59 while i < size:
60 sector = struct.pack('>l504xl', i / 512, i / 512)
61 file.write(sector)
62 i = i + 512
63 file.close()
66 class TestSingleDrive(ImageCommitTestCase):
67 image_len = 1 * 1024 * 1024
68 test_len = 1 * 1024 * 256
70 def setUp(self):
71 self.create_image(backing_img, TestSingleDrive.image_len)
72 qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
73 qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
74 qemu_io('-c', 'write -P 0xab 0 524288', backing_img)
75 qemu_io('-c', 'write -P 0xef 524288 524288', mid_img)
76 self.vm = iotests.VM().add_drive(test_img)
77 self.vm.launch()
79 def tearDown(self):
80 self.vm.shutdown()
81 os.remove(test_img)
82 os.remove(mid_img)
83 os.remove(backing_img)
85 def test_commit(self):
86 self.assert_no_active_commit()
87 result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img)
88 self.assert_qmp(result, 'return', {})
90 completed = False
91 while not completed:
92 for event in self.vm.get_qmp_events(wait=True):
93 if event['event'] == 'BLOCK_JOB_COMPLETED':
94 self.assert_qmp(event, 'data/type', 'commit')
95 self.assert_qmp(event, 'data/device', 'drive0')
96 self.assert_qmp(event, 'data/offset', self.image_len)
97 self.assert_qmp(event, 'data/len', self.image_len)
98 completed = True
100 self.assert_no_active_commit()
101 self.vm.shutdown()
103 self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
104 self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
106 def test_device_not_found(self):
107 result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img)
108 self.assert_qmp(result, 'error/class', 'DeviceNotFound')
110 def test_top_same_base(self):
111 self.assert_no_active_commit()
112 result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % backing_img)
113 self.assert_qmp(result, 'error/class', 'GenericError')
114 self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % backing_img)
116 def test_top_invalid(self):
117 self.assert_no_active_commit()
118 result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % backing_img)
119 self.assert_qmp(result, 'error/class', 'GenericError')
120 self.assert_qmp(result, 'error/desc', 'Top image file badfile not found')
122 def test_base_invalid(self):
123 self.assert_no_active_commit()
124 result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img, base='badfile')
125 self.assert_qmp(result, 'error/class', 'GenericError')
126 self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found')
128 def test_top_is_active(self):
129 self.assert_no_active_commit()
130 result = self.vm.qmp('block-commit', device='drive0', top='%s' % test_img, base='%s' % backing_img)
131 self.assert_qmp(result, 'error/class', 'GenericError')
132 self.assert_qmp(result, 'error/desc', 'Top image as the active layer is currently unsupported')
134 def test_top_and_base_reversed(self):
135 self.assert_no_active_commit()
136 result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img)
137 self.assert_qmp(result, 'error/class', 'GenericError')
138 self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img)
140 def test_top_omitted(self):
141 self.assert_no_active_commit()
142 result = self.vm.qmp('block-commit', device='drive0')
143 self.assert_qmp(result, 'error/class', 'GenericError')
144 self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing")
147 class TestSetSpeed(ImageCommitTestCase):
148 image_len = 80 * 1024 * 1024 # MB
150 def setUp(self):
151 qemu_img('create', backing_img, str(TestSetSpeed.image_len))
152 qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
153 qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
154 self.vm = iotests.VM().add_drive(test_img)
155 self.vm.launch()
157 def tearDown(self):
158 self.vm.shutdown()
159 os.remove(test_img)
160 os.remove(mid_img)
161 os.remove(backing_img)
163 def test_set_speed(self):
164 self.assert_no_active_commit()
166 result = self.vm.qmp('block-commit', device='drive0', top=mid_img, speed=1024 * 1024)
167 self.assert_qmp(result, 'return', {})
169 # Ensure the speed we set was accepted
170 result = self.vm.qmp('query-block-jobs')
171 self.assert_qmp(result, 'return[0]/device', 'drive0')
172 self.assert_qmp(result, 'return[0]/speed', 1024 * 1024)
174 self.cancel_and_wait()
177 if __name__ == '__main__':
178 iotests.main(supported_fmts=['qcow2', 'qed'])