| #!/usr/bin/env python3 | |
| # group: rw quick | |
| # | |
| # Test for when a backing file is considered overridden (thus, a | |
| # json:{} filename is generated for the overlay) and when it is not | |
| # | |
| # Copyright (C) 2018 Red Hat, Inc. | |
| # | |
| # This program is free software; you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation; either version 2 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # | |
| # Creator/Owner: Hanna Reitz <hreitz@redhat.com> | |
| import iotests | |
| from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \ | |
| filter_qmp_testfiles, filter_qmp_imgfmt | |
| # Need backing file and change-backing-file support | |
| iotests.script_initialize( | |
| supported_fmts=['qcow2', 'qed'], | |
| supported_platforms=['linux'], | |
| ) | |
| def log_node_info(node): | |
| log('') | |
| log('bs->filename: ' + node['image']['filename'], | |
| filters=[filter_testfiles, filter_imgfmt]) | |
| log('bs->backing_file: ' + node['image']['full-backing-filename'], | |
| filters=[filter_testfiles, filter_imgfmt]) | |
| if 'backing-image' in node['image']: | |
| log('bs->backing->bs->filename: ' + | |
| node['image']['backing-image']['filename'], | |
| filters=[filter_testfiles, filter_imgfmt]) | |
| else: | |
| log('bs->backing: (none)') | |
| log('') | |
| with iotests.FilePath('base.img') as base_img_path, \ | |
| iotests.FilePath('top.img') as top_img_path, \ | |
| iotests.VM() as vm: | |
| qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') | |
| # Choose a funny way to describe the backing filename | |
| qemu_img('create', '-f', iotests.imgfmt, '-b', | |
| 'file:' + base_img_path, '-F', iotests.imgfmt, | |
| top_img_path) | |
| vm.launch() | |
| log('--- Implicit backing file ---') | |
| log('') | |
| vm.qmp_log('blockdev-add', | |
| node_name='node0', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': top_img_path | |
| }, | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| # Filename should be plain, and the backing node filename should | |
| # not contain the "file:" prefix | |
| log_node_info(vm.node_info('node0')) | |
| vm.qmp_log('blockdev-del', node_name='node0') | |
| log('') | |
| log('--- change-backing-file ---') | |
| log('') | |
| vm.qmp_log('blockdev-add', | |
| node_name='node0', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': top_img_path | |
| }, | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| # Changing the backing file to a qemu-reported filename should | |
| # result in qemu accepting the corresponding BDS as the implicit | |
| # backing BDS (and thus not generate a json:{} filename). | |
| # So, first, query the backing filename. | |
| backing_filename = \ | |
| vm.node_info('node0')['image']['backing-image']['filename'] | |
| # Next, change the backing file to something different | |
| vm.qmp_log('change-backing-file', | |
| image_node_name='node0', | |
| device='node0', | |
| backing_file='null-co://', | |
| filters=[filter_qmp_testfiles]) | |
| # Now, verify that we get a json:{} filename | |
| # (Image header says "null-co://", actual backing file still is | |
| # base_img_path) | |
| log_node_info(vm.node_info('node0')) | |
| # Change it back | |
| # (To get header and backing file in sync) | |
| vm.qmp_log('change-backing-file', | |
| image_node_name='node0', | |
| device='node0', | |
| backing_file=backing_filename, | |
| filters=[filter_qmp_testfiles]) | |
| # And verify that we get our original results | |
| log_node_info(vm.node_info('node0')) | |
| # Finally, try a "file:" prefix. While this is actually what we | |
| # originally had in the image header, qemu will not reopen the | |
| # backing file here, so it cannot verify that this filename | |
| # "resolves" to the actual backing BDS's filename and will thus | |
| # consider both to be different. | |
| # (This may be fixed in the future.) | |
| vm.qmp_log('change-backing-file', | |
| image_node_name='node0', | |
| device='node0', | |
| backing_file=('file:' + backing_filename), | |
| filters=[filter_qmp_testfiles]) | |
| # So now we should get a json:{} filename | |
| log_node_info(vm.node_info('node0')) | |
| # Remove and re-attach so we can see that (as in our first try), | |
| # opening the image anew helps qemu resolve the header backing | |
| # filename. | |
| vm.qmp_log('blockdev-del', node_name='node0') | |
| vm.qmp_log('blockdev-add', | |
| node_name='node0', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': top_img_path | |
| }, | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| log_node_info(vm.node_info('node0')) | |
| vm.qmp_log('blockdev-del', node_name='node0') | |
| log('') | |
| log('--- Override backing file ---') | |
| log('') | |
| # For this test, we need the plain filename in the image header | |
| # (because qemu cannot "canonicalize"/"resolve" the backing | |
| # filename unless the backing file is opened implicitly with the | |
| # overlay) | |
| qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, | |
| '-F', iotests.imgfmt, top_img_path) | |
| # You can only reliably override backing options by using a node | |
| # reference (or by specifying file.filename, but, well...) | |
| vm.qmp_log('blockdev-add', node_name='null', driver='null-co') | |
| vm.qmp_log('blockdev-add', | |
| node_name='node0', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': top_img_path | |
| }, | |
| backing='null', | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| # Should get a json:{} filename (and bs->backing_file is | |
| # null-co://, because that field actually has not much to do | |
| # with the header backing filename (except that it is changed by | |
| # change-backing-file)) | |
| log_node_info(vm.node_info('node0')) | |
| # Detach the backing file by reopening the whole thing | |
| vm.qmp_log('blockdev-del', node_name='node0') | |
| vm.qmp_log('blockdev-del', node_name='null') | |
| vm.qmp_log('blockdev-add', | |
| node_name='node0', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': top_img_path | |
| }, | |
| backing=None, | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| # Should get a json:{} filename (because we overrode the backing | |
| # file to not be there) | |
| log_node_info(vm.node_info('node0')) | |
| # Open the original backing file | |
| vm.qmp_log('blockdev-add', | |
| node_name='original-backing', | |
| driver=iotests.imgfmt, | |
| file={ | |
| 'driver': 'file', | |
| 'filename': base_img_path | |
| }, | |
| filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) | |
| # Attach the original backing file to its overlay | |
| vm.qmp_log('blockdev-snapshot', | |
| node='original-backing', | |
| overlay='node0') | |
| # This should give us the original plain result | |
| log_node_info(vm.node_info('node0')) | |
| vm.qmp_log('blockdev-del', node_name='node0') | |
| vm.qmp_log('blockdev-del', node_name='original-backing') | |
| vm.shutdown() |