xref: /qemu/tests/qemu-iotests/206 (revision b21e2380)
1#!/usr/bin/env python3
2# group: rw
3#
4# Test qcow2 and file image creation
5#
6# Copyright (C) 2018 Red Hat, Inc.
7#
8# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22#
23
24import iotests
25from iotests import imgfmt
26
27iotests.script_initialize(supported_fmts=['qcow2'],
28                          supported_protocols=['file'])
29iotests.verify_working_luks()
30
31with iotests.FilePath('t.qcow2') as disk_path, \
32     iotests.FilePath('t.qcow2.base') as backing_path, \
33     iotests.VM() as vm:
34
35    vm.add_object('secret,id=keysec0,data=foo')
36
37    #
38    # Successful image creation (defaults)
39    #
40    iotests.log("=== Successful image creation (defaults) ===")
41    iotests.log("")
42
43    size = 128 * 1024 * 1024
44
45    vm.launch()
46    vm.blockdev_create({ 'driver': 'file',
47                         'filename': disk_path,
48                         'size': 0 })
49
50    vm.qmp_log('blockdev-add',
51               filters=[iotests.filter_qmp_testfiles],
52               driver='file', filename=disk_path,
53               node_name='imgfile')
54
55    vm.blockdev_create({ 'driver': imgfmt,
56                         'file': 'imgfile',
57                         'size': size })
58    vm.shutdown()
59
60    iotests.img_info_log(disk_path)
61
62    #
63    # Successful image creation (inline blockdev-add, explicit defaults)
64    #
65    iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===")
66    iotests.log("")
67
68    # Choose a different size to show that we got a new image
69    size = 64 * 1024 * 1024
70
71    vm.launch()
72    vm.blockdev_create({ 'driver': 'file',
73                         'filename': disk_path,
74                         'size': 0,
75                         'preallocation': 'off',
76                         'nocow': False })
77
78    vm.blockdev_create({ 'driver': imgfmt,
79                         'file': {
80                             'driver': 'file',
81                             'filename': disk_path,
82                         },
83                         'size': size,
84                         'version': 'v3',
85                         'cluster-size': 65536,
86                         'preallocation': 'off',
87                         'lazy-refcounts': False,
88                         'refcount-bits': 16 })
89    vm.shutdown()
90
91    iotests.img_info_log(disk_path)
92
93    #
94    # Successful image creation (v3 non-default options)
95    #
96    iotests.log("=== Successful image creation (v3 non-default options) ===")
97    iotests.log("")
98
99    # Choose a different size to show that we got a new image
100    size = 32 * 1024 * 1024
101
102    vm.launch()
103    vm.blockdev_create({ 'driver': 'file',
104                         'filename': disk_path,
105                         'size': 0,
106                         'preallocation': 'falloc',
107                         'nocow': True })
108
109    vm.blockdev_create({ 'driver': imgfmt,
110                         'file': {
111                             'driver': 'file',
112                             'filename': disk_path,
113                         },
114                         'size': size,
115                         'version': 'v3',
116                         'cluster-size': 2097152,
117                         'preallocation': 'metadata',
118                         'lazy-refcounts': True,
119                         'refcount-bits': 1 })
120    vm.shutdown()
121
122    iotests.img_info_log(disk_path)
123
124    #
125    # Successful image creation (v2 non-default options)
126    #
127    iotests.log("=== Successful image creation (v2 non-default options) ===")
128    iotests.log("")
129
130    vm.launch()
131    vm.blockdev_create({ 'driver': 'file',
132                         'filename': disk_path,
133                         'size': 0 })
134
135    vm.blockdev_create({ 'driver': imgfmt,
136                         'file': {
137                             'driver': 'file',
138                             'filename': disk_path,
139                         },
140                         'size': size,
141                         'backing-file': backing_path,
142                         'backing-fmt': 'qcow2',
143                         'version': 'v2',
144                         'cluster-size': 512 })
145    vm.shutdown()
146
147    iotests.img_info_log(disk_path)
148
149    #
150    # Successful image creation (encrypted)
151    #
152    iotests.log("=== Successful image creation (encrypted) ===")
153    iotests.log("")
154
155    vm.launch()
156    vm.blockdev_create({ 'driver': imgfmt,
157                         'file': {
158                             'driver': 'file',
159                             'filename': disk_path,
160                         },
161                         'size': size,
162                         'encrypt': {
163                             'format': 'luks',
164                             'key-secret': 'keysec0',
165                             'cipher-alg': 'aes-128',
166                             'cipher-mode': 'cbc',
167                             'ivgen-alg': 'plain64',
168                             'ivgen-hash-alg': 'md5',
169                             'hash-alg': 'sha1',
170                             'iter-time': 10,
171                         }})
172    vm.shutdown()
173
174    iotests.img_info_log(disk_path)
175
176    #
177    # Invalid BlockdevRef
178    #
179    iotests.log("=== Invalid BlockdevRef ===")
180    iotests.log("")
181
182    vm.launch()
183    vm.blockdev_create({ 'driver': imgfmt,
184                         'file': "this doesn't exist",
185                         'size': size })
186    vm.shutdown()
187
188    #
189    # Invalid sizes
190    #
191    iotests.log("=== Invalid sizes ===")
192
193    # TODO Negative image sizes aren't handled correctly, but this is a problem
194    # with QAPI's implementation of the 'size' type and affects other commands
195    # as well. Once this is fixed, we may want to add a test case here.
196    #
197    # 1. Misaligned image size
198    # 2. 2^64 - 512
199    # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
200    # 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size)
201
202    vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
203
204    vm.launch()
205    for size in [ 1234, 18446744073709551104, 9223372036854775808,
206                  9223372036854775296, 9223372035781033984 ]:
207        vm.blockdev_create({ 'driver': imgfmt,
208                             'file': 'node0',
209                             'size': size })
210    vm.shutdown()
211
212    #
213    # Invalid version
214    #
215    iotests.log("=== Invalid version ===")
216
217    vm.launch()
218    vm.blockdev_create({ 'driver': imgfmt,
219                         'file': 'node0',
220                         'size': 67108864,
221                         'version': 'v1' })
222    vm.blockdev_create({ 'driver': imgfmt,
223                         'file': 'node0',
224                         'size': 67108864,
225                         'version': 'v2',
226                         'lazy-refcounts': True })
227    vm.blockdev_create({ 'driver': imgfmt,
228                         'file': 'node0',
229                         'size': 67108864,
230                         'version': 'v2',
231                         'refcount-bits': 8 })
232    vm.shutdown()
233
234    #
235    # Invalid backing file options
236    #
237    iotests.log("=== Invalid backing file options ===")
238
239    vm.launch()
240    vm.blockdev_create({ 'driver': imgfmt,
241                         'file': 'node0',
242                         'size': 67108864,
243                         'backing-file': '/dev/null',
244                         'preallocation': 'full' })
245    vm.blockdev_create({ 'driver': imgfmt,
246                         'file': 'node0',
247                         'size': 67108864,
248                         'backing-fmt': imgfmt })
249    vm.shutdown()
250
251    #
252    # Invalid cluster size
253    #
254    iotests.log("=== Invalid cluster size ===")
255
256    vm.launch()
257    for csize in [ 1234, 128, 4194304, 0 ]:
258        vm.blockdev_create({ 'driver': imgfmt,
259                             'file': 'node0',
260                             'size': 67108864,
261                             'cluster-size': csize })
262    vm.blockdev_create({ 'driver': imgfmt,
263                         'file': 'node0',
264                         'size': 281474976710656,
265                         'cluster-size': 512 })
266    vm.shutdown()
267
268    #
269    # Invalid refcount width
270    #
271    iotests.log("=== Invalid refcount width ===")
272
273    vm.launch()
274    for refcount_bits in [ 128, 0, 7 ]:
275        vm.blockdev_create({ 'driver': imgfmt,
276                             'file': 'node0',
277                             'size': 67108864,
278                             'refcount-bits': refcount_bits })
279    vm.shutdown()
280