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