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