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