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