1#!/usr/bin/env python3 2# group: rw quick 3# 4# Test for when a backing file is considered overridden (thus, a 5# json:{} filename is generated for the overlay) and when it is not 6# 7# Copyright (C) 2018 Red Hat, Inc. 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# Creator/Owner: Max Reitz <mreitz@redhat.com> 23 24import iotests 25from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \ 26 filter_qmp_testfiles, filter_qmp_imgfmt 27 28# Need backing file and change-backing-file support 29iotests.script_initialize( 30 supported_fmts=['qcow2', 'qed'], 31 supported_platforms=['linux'], 32) 33 34 35def log_node_info(node): 36 log('') 37 38 log('bs->filename: ' + node['image']['filename'], 39 filters=[filter_testfiles, filter_imgfmt]) 40 log('bs->backing_file: ' + node['image']['full-backing-filename'], 41 filters=[filter_testfiles, filter_imgfmt]) 42 43 if 'backing-image' in node['image']: 44 log('bs->backing->bs->filename: ' + 45 node['image']['backing-image']['filename'], 46 filters=[filter_testfiles, filter_imgfmt]) 47 else: 48 log('bs->backing: (none)') 49 50 log('') 51 52 53with iotests.FilePath('base.img') as base_img_path, \ 54 iotests.FilePath('top.img') as top_img_path, \ 55 iotests.VM() as vm: 56 57 assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 58 # Choose a funny way to describe the backing filename 59 assert qemu_img('create', '-f', iotests.imgfmt, '-b', 60 'file:' + base_img_path, '-F', iotests.imgfmt, 61 top_img_path) == 0 62 63 vm.launch() 64 65 log('--- Implicit backing file ---') 66 log('') 67 68 vm.qmp_log('blockdev-add', 69 node_name='node0', 70 driver=iotests.imgfmt, 71 file={ 72 'driver': 'file', 73 'filename': top_img_path 74 }, 75 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 76 77 # Filename should be plain, and the backing node filename should 78 # not contain the "file:" prefix 79 log_node_info(vm.node_info('node0')) 80 81 vm.qmp_log('blockdev-del', node_name='node0') 82 83 log('') 84 log('--- change-backing-file ---') 85 log('') 86 87 vm.qmp_log('blockdev-add', 88 node_name='node0', 89 driver=iotests.imgfmt, 90 file={ 91 'driver': 'file', 92 'filename': top_img_path 93 }, 94 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 95 96 # Changing the backing file to a qemu-reported filename should 97 # result in qemu accepting the corresponding BDS as the implicit 98 # backing BDS (and thus not generate a json:{} filename). 99 # So, first, query the backing filename. 100 101 backing_filename = \ 102 vm.node_info('node0')['image']['backing-image']['filename'] 103 104 # Next, change the backing file to something different 105 106 vm.qmp_log('change-backing-file', 107 image_node_name='node0', 108 device='node0', 109 backing_file='null-co://', 110 filters=[filter_qmp_testfiles]) 111 112 # Now, verify that we get a json:{} filename 113 # (Image header says "null-co://", actual backing file still is 114 # base_img_path) 115 116 log_node_info(vm.node_info('node0')) 117 118 # Change it back 119 # (To get header and backing file in sync) 120 121 vm.qmp_log('change-backing-file', 122 image_node_name='node0', 123 device='node0', 124 backing_file=backing_filename, 125 filters=[filter_qmp_testfiles]) 126 127 # And verify that we get our original results 128 129 log_node_info(vm.node_info('node0')) 130 131 # Finally, try a "file:" prefix. While this is actually what we 132 # originally had in the image header, qemu will not reopen the 133 # backing file here, so it cannot verify that this filename 134 # "resolves" to the actual backing BDS's filename and will thus 135 # consider both to be different. 136 # (This may be fixed in the future.) 137 138 vm.qmp_log('change-backing-file', 139 image_node_name='node0', 140 device='node0', 141 backing_file=('file:' + backing_filename), 142 filters=[filter_qmp_testfiles]) 143 144 # So now we should get a json:{} filename 145 146 log_node_info(vm.node_info('node0')) 147 148 # Remove and re-attach so we can see that (as in our first try), 149 # opening the image anew helps qemu resolve the header backing 150 # filename. 151 152 vm.qmp_log('blockdev-del', node_name='node0') 153 154 vm.qmp_log('blockdev-add', 155 node_name='node0', 156 driver=iotests.imgfmt, 157 file={ 158 'driver': 'file', 159 'filename': top_img_path 160 }, 161 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 162 163 log_node_info(vm.node_info('node0')) 164 165 vm.qmp_log('blockdev-del', node_name='node0') 166 167 log('') 168 log('--- Override backing file ---') 169 log('') 170 171 # For this test, we need the plain filename in the image header 172 # (because qemu cannot "canonicalize"/"resolve" the backing 173 # filename unless the backing file is opened implicitly with the 174 # overlay) 175 assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, 176 '-F', iotests.imgfmt, top_img_path) == 0 177 178 # You can only reliably override backing options by using a node 179 # reference (or by specifying file.filename, but, well...) 180 vm.qmp_log('blockdev-add', node_name='null', driver='null-co') 181 182 vm.qmp_log('blockdev-add', 183 node_name='node0', 184 driver=iotests.imgfmt, 185 file={ 186 'driver': 'file', 187 'filename': top_img_path 188 }, 189 backing='null', 190 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 191 192 # Should get a json:{} filename (and bs->backing_file is 193 # null-co://, because that field actually has not much to do 194 # with the header backing filename (except that it is changed by 195 # change-backing-file)) 196 197 log_node_info(vm.node_info('node0')) 198 199 # Detach the backing file by reopening the whole thing 200 201 vm.qmp_log('blockdev-del', node_name='node0') 202 vm.qmp_log('blockdev-del', node_name='null') 203 204 vm.qmp_log('blockdev-add', 205 node_name='node0', 206 driver=iotests.imgfmt, 207 file={ 208 'driver': 'file', 209 'filename': top_img_path 210 }, 211 backing=None, 212 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 213 214 # Should get a json:{} filename (because we overrode the backing 215 # file to not be there) 216 217 log_node_info(vm.node_info('node0')) 218 219 # Open the original backing file 220 221 vm.qmp_log('blockdev-add', 222 node_name='original-backing', 223 driver=iotests.imgfmt, 224 file={ 225 'driver': 'file', 226 'filename': base_img_path 227 }, 228 filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) 229 230 # Attach the original backing file to its overlay 231 232 vm.qmp_log('blockdev-snapshot', 233 node='original-backing', 234 overlay='node0') 235 236 # This should give us the original plain result 237 238 log_node_info(vm.node_info('node0')) 239 240 vm.qmp_log('blockdev-del', node_name='node0') 241 vm.qmp_log('blockdev-del', node_name='original-backing') 242 243 vm.shutdown() 244