| #!/usr/bin/env python3 |
| # |
| # 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: Max Reitz <mreitz@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.verify_image_format(supported_fmts=['qcow2', 'qed']) |
| iotests.verify_platform(['linux']) |
| |
| |
| def log_node_info(node): |
| log('') |
| |
| log('bs->filename: ' + node['image']['filename'], |
| filters=[filter_testfiles, filter_imgfmt]) |
| log('bs->backing_file: ' + node['backing_file'], |
| 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: |
| |
| assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 |
| # Choose a funny way to describe the backing filename |
| assert qemu_img('create', '-f', iotests.imgfmt, '-b', |
| 'file:' + base_img_path, top_img_path) == 0 |
| |
| 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 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) |
| assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, |
| top_img_path) == 0 |
| |
| # 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() |