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