xref: /openbmc/qemu/tests/qemu-iotests/228 (revision 7a1bfee6)
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