xref: /qemu/tests/qemu-iotests/206 (revision abff1abf)
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'])
27iotests.verify_working_luks()
28
29with iotests.FilePath('t.qcow2') as disk_path, \
30     iotests.FilePath('t.qcow2.base') as backing_path, \
31     iotests.VM() as vm:
32
33    vm.add_object('secret,id=keysec0,data=foo')
34
35    #
36    # Successful image creation (defaults)
37    #
38    iotests.log("=== Successful image creation (defaults) ===")
39    iotests.log("")
40
41    size = 128 * 1024 * 1024
42
43    vm.launch()
44    vm.blockdev_create({ 'driver': 'file',
45                         'filename': disk_path,
46                         'size': 0 })
47
48    vm.qmp_log('blockdev-add',
49               filters=[iotests.filter_qmp_testfiles],
50               driver='file', filename=disk_path,
51               node_name='imgfile')
52
53    vm.blockdev_create({ 'driver': imgfmt,
54                         'file': 'imgfile',
55                         'size': size })
56    vm.shutdown()
57
58    iotests.img_info_log(disk_path)
59
60    #
61    # Successful image creation (inline blockdev-add, explicit defaults)
62    #
63    iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===")
64    iotests.log("")
65
66    # Choose a different size to show that we got a new image
67    size = 64 * 1024 * 1024
68
69    vm.launch()
70    vm.blockdev_create({ 'driver': 'file',
71                         'filename': disk_path,
72                         'size': 0,
73                         'preallocation': 'off',
74                         'nocow': False })
75
76    vm.blockdev_create({ 'driver': imgfmt,
77                         'file': {
78                             'driver': 'file',
79                             'filename': disk_path,
80                         },
81                         'size': size,
82                         'version': 'v3',
83                         'cluster-size': 65536,
84                         'preallocation': 'off',
85                         'lazy-refcounts': False,
86                         'refcount-bits': 16 })
87    vm.shutdown()
88
89    iotests.img_info_log(disk_path)
90
91    #
92    # Successful image creation (v3 non-default options)
93    #
94    iotests.log("=== Successful image creation (v3 non-default options) ===")
95    iotests.log("")
96
97    # Choose a different size to show that we got a new image
98    size = 32 * 1024 * 1024
99
100    vm.launch()
101    vm.blockdev_create({ 'driver': 'file',
102                         'filename': disk_path,
103                         'size': 0,
104                         'preallocation': 'falloc',
105                         'nocow': True })
106
107    vm.blockdev_create({ 'driver': imgfmt,
108                         'file': {
109                             'driver': 'file',
110                             'filename': disk_path,
111                         },
112                         'size': size,
113                         'version': 'v3',
114                         'cluster-size': 2097152,
115                         'preallocation': 'metadata',
116                         'lazy-refcounts': True,
117                         'refcount-bits': 1 })
118    vm.shutdown()
119
120    iotests.img_info_log(disk_path)
121
122    #
123    # Successful image creation (v2 non-default options)
124    #
125    iotests.log("=== Successful image creation (v2 non-default options) ===")
126    iotests.log("")
127
128    vm.launch()
129    vm.blockdev_create({ 'driver': 'file',
130                         'filename': disk_path,
131                         'size': 0 })
132
133    vm.blockdev_create({ 'driver': imgfmt,
134                         'file': {
135                             'driver': 'file',
136                             'filename': disk_path,
137                         },
138                         'size': size,
139                         'backing-file': backing_path,
140                         'backing-fmt': 'qcow2',
141                         'version': 'v2',
142                         'cluster-size': 512 })
143    vm.shutdown()
144
145    iotests.img_info_log(disk_path)
146
147    #
148    # Successful image creation (encrypted)
149    #
150    iotests.log("=== Successful image creation (encrypted) ===")
151    iotests.log("")
152
153    vm.launch()
154    vm.blockdev_create({ 'driver': imgfmt,
155                         'file': {
156                             'driver': 'file',
157                             'filename': disk_path,
158                         },
159                         'size': size,
160                         'encrypt': {
161                             'format': 'luks',
162                             'key-secret': 'keysec0',
163                             'cipher-alg': 'twofish-128',
164                             'cipher-mode': 'ctr',
165                             'ivgen-alg': 'plain64',
166                             'ivgen-hash-alg': 'md5',
167                             'hash-alg': 'sha1',
168                             'iter-time': 10,
169                         }})
170    vm.shutdown()
171
172    iotests.img_info_log(disk_path)
173
174    #
175    # Invalid BlockdevRef
176    #
177    iotests.log("=== Invalid BlockdevRef ===")
178    iotests.log("")
179
180    vm.launch()
181    vm.blockdev_create({ 'driver': imgfmt,
182                         'file': "this doesn't exist",
183                         'size': size })
184    vm.shutdown()
185
186    #
187    # Invalid sizes
188    #
189    iotests.log("=== Invalid sizes ===")
190
191    # TODO Negative image sizes aren't handled correctly, but this is a problem
192    # with QAPI's implementation of the 'size' type and affects other commands
193    # as well. Once this is fixed, we may want to add a test case here.
194    #
195    # 1. Misaligned image size
196    # 2. 2^64 - 512
197    # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
198    # 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size)
199
200    vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
201
202    vm.launch()
203    for size in [ 1234, 18446744073709551104, 9223372036854775808,
204                  9223372036854775296 ]:
205        vm.blockdev_create({ 'driver': imgfmt,
206                             'file': 'node0',
207                             'size': size })
208    vm.shutdown()
209
210    #
211    # Invalid version
212    #
213    iotests.log("=== Invalid version ===")
214
215    vm.launch()
216    vm.blockdev_create({ 'driver': imgfmt,
217                         'file': 'node0',
218                         'size': 67108864,
219                         'version': 'v1' })
220    vm.blockdev_create({ 'driver': imgfmt,
221                         'file': 'node0',
222                         'size': 67108864,
223                         'version': 'v2',
224                         'lazy-refcounts': True })
225    vm.blockdev_create({ 'driver': imgfmt,
226                         'file': 'node0',
227                         'size': 67108864,
228                         'version': 'v2',
229                         'refcount-bits': 8 })
230    vm.shutdown()
231
232    #
233    # Invalid backing file options
234    #
235    iotests.log("=== Invalid backing file options ===")
236
237    vm.launch()
238    vm.blockdev_create({ 'driver': imgfmt,
239                         'file': 'node0',
240                         'size': 67108864,
241                         'backing-file': '/dev/null',
242                         'preallocation': 'full' })
243    vm.blockdev_create({ 'driver': imgfmt,
244                         'file': 'node0',
245                         'size': 67108864,
246                         'backing-fmt': imgfmt })
247    vm.shutdown()
248
249    #
250    # Invalid cluster size
251    #
252    iotests.log("=== Invalid cluster size ===")
253
254    vm.launch()
255    for csize in [ 1234, 128, 4194304, 0 ]:
256        vm.blockdev_create({ 'driver': imgfmt,
257                             'file': 'node0',
258                             'size': 67108864,
259                             'cluster-size': csize })
260    vm.blockdev_create({ 'driver': imgfmt,
261                         'file': 'node0',
262                         'size': 281474976710656,
263                         'cluster-size': 512 })
264    vm.shutdown()
265
266    #
267    # Invalid refcount width
268    #
269    iotests.log("=== Invalid refcount width ===")
270
271    vm.launch()
272    for refcount_bits in [ 128, 0, 7 ]:
273        vm.blockdev_create({ 'driver': imgfmt,
274                             'file': 'node0',
275                             'size': 67108864,
276                             'refcount-bits': refcount_bits })
277    vm.shutdown()
278