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