xref: /openbmc/qemu/tests/qemu-iotests/228 (revision 0f62cd8204163ba082056094a0bcb693faf67bf6)
1*0f62cd82SMax Reitz#!/usr/bin/env python
2*0f62cd82SMax Reitz#
3*0f62cd82SMax Reitz# Test for when a backing file is considered overridden (thus, a
4*0f62cd82SMax Reitz# json:{} filename is generated for the overlay) and when it is not
5*0f62cd82SMax Reitz#
6*0f62cd82SMax Reitz# Copyright (C) 2018 Red Hat, Inc.
7*0f62cd82SMax Reitz#
8*0f62cd82SMax Reitz# This program is free software; you can redistribute it and/or modify
9*0f62cd82SMax Reitz# it under the terms of the GNU General Public License as published by
10*0f62cd82SMax Reitz# the Free Software Foundation; either version 2 of the License, or
11*0f62cd82SMax Reitz# (at your option) any later version.
12*0f62cd82SMax Reitz#
13*0f62cd82SMax Reitz# This program is distributed in the hope that it will be useful,
14*0f62cd82SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of
15*0f62cd82SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*0f62cd82SMax Reitz# GNU General Public License for more details.
17*0f62cd82SMax Reitz#
18*0f62cd82SMax Reitz# You should have received a copy of the GNU General Public License
19*0f62cd82SMax Reitz# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*0f62cd82SMax Reitz#
21*0f62cd82SMax Reitz# Creator/Owner: Max Reitz <mreitz@redhat.com>
22*0f62cd82SMax Reitz
23*0f62cd82SMax Reitzimport iotests
24*0f62cd82SMax Reitzfrom iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
25*0f62cd82SMax Reitz        filter_qmp_testfiles, filter_qmp_imgfmt
26*0f62cd82SMax Reitz
27*0f62cd82SMax Reitz# Need backing file and change-backing-file support
28*0f62cd82SMax Reitziotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
29*0f62cd82SMax Reitziotests.verify_platform(['linux'])
30*0f62cd82SMax Reitz
31*0f62cd82SMax Reitz
32*0f62cd82SMax Reitzdef log_node_info(node):
33*0f62cd82SMax Reitz    log('')
34*0f62cd82SMax Reitz
35*0f62cd82SMax Reitz    log('bs->filename: ' + node['image']['filename'],
36*0f62cd82SMax Reitz        filters=[filter_testfiles, filter_imgfmt])
37*0f62cd82SMax Reitz    log('bs->backing_file: ' + node['backing_file'],
38*0f62cd82SMax Reitz        filters=[filter_testfiles, filter_imgfmt])
39*0f62cd82SMax Reitz
40*0f62cd82SMax Reitz    if 'backing-image' in node['image']:
41*0f62cd82SMax Reitz        log('bs->backing->bs->filename: ' +
42*0f62cd82SMax Reitz            node['image']['backing-image']['filename'],
43*0f62cd82SMax Reitz            filters=[filter_testfiles, filter_imgfmt])
44*0f62cd82SMax Reitz    else:
45*0f62cd82SMax Reitz        log('bs->backing: (none)')
46*0f62cd82SMax Reitz
47*0f62cd82SMax Reitz    log('')
48*0f62cd82SMax Reitz
49*0f62cd82SMax Reitz
50*0f62cd82SMax Reitzwith iotests.FilePath('base.img') as base_img_path, \
51*0f62cd82SMax Reitz     iotests.FilePath('top.img') as top_img_path, \
52*0f62cd82SMax Reitz     iotests.VM() as vm:
53*0f62cd82SMax Reitz
54*0f62cd82SMax Reitz    assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
55*0f62cd82SMax Reitz    # Choose a funny way to describe the backing filename
56*0f62cd82SMax Reitz    assert qemu_img('create', '-f', iotests.imgfmt, '-b',
57*0f62cd82SMax Reitz                    'file:' + base_img_path, top_img_path) == 0
58*0f62cd82SMax Reitz
59*0f62cd82SMax Reitz    vm.launch()
60*0f62cd82SMax Reitz
61*0f62cd82SMax Reitz    log('--- Implicit backing file ---')
62*0f62cd82SMax Reitz    log('')
63*0f62cd82SMax Reitz
64*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
65*0f62cd82SMax Reitz                node_name='node0',
66*0f62cd82SMax Reitz                driver=iotests.imgfmt,
67*0f62cd82SMax Reitz                file={
68*0f62cd82SMax Reitz                    'driver': 'file',
69*0f62cd82SMax Reitz                    'filename': top_img_path
70*0f62cd82SMax Reitz                },
71*0f62cd82SMax Reitz                filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
72*0f62cd82SMax Reitz
73*0f62cd82SMax Reitz    # Filename should be plain, and the backing filename should not
74*0f62cd82SMax Reitz    # contain the "file:" prefix
75*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
76*0f62cd82SMax Reitz
77*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='node0')
78*0f62cd82SMax Reitz
79*0f62cd82SMax Reitz    log('')
80*0f62cd82SMax Reitz    log('--- change-backing-file ---')
81*0f62cd82SMax Reitz    log('')
82*0f62cd82SMax Reitz
83*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
84*0f62cd82SMax Reitz               node_name='node0',
85*0f62cd82SMax Reitz               driver=iotests.imgfmt,
86*0f62cd82SMax Reitz               file={
87*0f62cd82SMax Reitz                   'driver': 'file',
88*0f62cd82SMax Reitz                   'filename': top_img_path
89*0f62cd82SMax Reitz               },
90*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
91*0f62cd82SMax Reitz
92*0f62cd82SMax Reitz    # Changing the backing file to a qemu-reported filename should
93*0f62cd82SMax Reitz    # result in qemu accepting the corresponding BDS as the implicit
94*0f62cd82SMax Reitz    # backing BDS (and thus not generate a json:{} filename).
95*0f62cd82SMax Reitz    # So, first, query the backing filename.
96*0f62cd82SMax Reitz
97*0f62cd82SMax Reitz    backing_filename = \
98*0f62cd82SMax Reitz        vm.node_info('node0')['image']['backing-image']['filename']
99*0f62cd82SMax Reitz
100*0f62cd82SMax Reitz    # Next, change the backing file to something different
101*0f62cd82SMax Reitz
102*0f62cd82SMax Reitz    vm.qmp_log('change-backing-file',
103*0f62cd82SMax Reitz               image_node_name='node0',
104*0f62cd82SMax Reitz               device='node0',
105*0f62cd82SMax Reitz               backing_file='null-co://',
106*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles])
107*0f62cd82SMax Reitz
108*0f62cd82SMax Reitz    # Now, verify that we get a json:{} filename
109*0f62cd82SMax Reitz    # (Image header says "null-co://", actual backing file still is
110*0f62cd82SMax Reitz    # base_img_path)
111*0f62cd82SMax Reitz
112*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
113*0f62cd82SMax Reitz
114*0f62cd82SMax Reitz    # Change it back
115*0f62cd82SMax Reitz    # (To get header and backing file in sync)
116*0f62cd82SMax Reitz
117*0f62cd82SMax Reitz    vm.qmp_log('change-backing-file',
118*0f62cd82SMax Reitz               image_node_name='node0',
119*0f62cd82SMax Reitz               device='node0',
120*0f62cd82SMax Reitz               backing_file=backing_filename,
121*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles])
122*0f62cd82SMax Reitz
123*0f62cd82SMax Reitz    # And verify that we get our original results
124*0f62cd82SMax Reitz
125*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
126*0f62cd82SMax Reitz
127*0f62cd82SMax Reitz    # Finally, try a "file:" prefix.  While this is actually what we
128*0f62cd82SMax Reitz    # originally had in the image header, qemu will not reopen the
129*0f62cd82SMax Reitz    # backing file here, so it cannot verify that this filename
130*0f62cd82SMax Reitz    # "resolves" to the actual backing BDS's filename and will thus
131*0f62cd82SMax Reitz    # consider both to be different.
132*0f62cd82SMax Reitz    # (This may be fixed in the future.)
133*0f62cd82SMax Reitz
134*0f62cd82SMax Reitz    vm.qmp_log('change-backing-file',
135*0f62cd82SMax Reitz               image_node_name='node0',
136*0f62cd82SMax Reitz               device='node0',
137*0f62cd82SMax Reitz               backing_file=('file:' + backing_filename),
138*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles])
139*0f62cd82SMax Reitz
140*0f62cd82SMax Reitz    # So now we should get a json:{} filename
141*0f62cd82SMax Reitz
142*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
143*0f62cd82SMax Reitz
144*0f62cd82SMax Reitz    # Remove and re-attach so we can see that (as in our first try),
145*0f62cd82SMax Reitz    # opening the image anew helps qemu resolve the header backing
146*0f62cd82SMax Reitz    # filename.
147*0f62cd82SMax Reitz
148*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='node0')
149*0f62cd82SMax Reitz
150*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
151*0f62cd82SMax Reitz               node_name='node0',
152*0f62cd82SMax Reitz               driver=iotests.imgfmt,
153*0f62cd82SMax Reitz               file={
154*0f62cd82SMax Reitz                   'driver': 'file',
155*0f62cd82SMax Reitz                   'filename': top_img_path
156*0f62cd82SMax Reitz               },
157*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
158*0f62cd82SMax Reitz
159*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
160*0f62cd82SMax Reitz
161*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='node0')
162*0f62cd82SMax Reitz
163*0f62cd82SMax Reitz    log('')
164*0f62cd82SMax Reitz    log('--- Override backing file ---')
165*0f62cd82SMax Reitz    log('')
166*0f62cd82SMax Reitz
167*0f62cd82SMax Reitz    # For this test, we need the plain filename in the image header
168*0f62cd82SMax Reitz    # (because qemu cannot "canonicalize"/"resolve" the backing
169*0f62cd82SMax Reitz    # filename unless the backing file is opened implicitly with the
170*0f62cd82SMax Reitz    # overlay)
171*0f62cd82SMax Reitz    assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
172*0f62cd82SMax Reitz                    top_img_path) == 0
173*0f62cd82SMax Reitz
174*0f62cd82SMax Reitz    # You can only reliably override backing options by using a node
175*0f62cd82SMax Reitz    # reference (or by specifying file.filename, but, well...)
176*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add', node_name='null', driver='null-co')
177*0f62cd82SMax Reitz
178*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
179*0f62cd82SMax Reitz               node_name='node0',
180*0f62cd82SMax Reitz               driver=iotests.imgfmt,
181*0f62cd82SMax Reitz               file={
182*0f62cd82SMax Reitz                   'driver': 'file',
183*0f62cd82SMax Reitz                   'filename': top_img_path
184*0f62cd82SMax Reitz               },
185*0f62cd82SMax Reitz               backing='null',
186*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
187*0f62cd82SMax Reitz
188*0f62cd82SMax Reitz    # Should get a json:{} filename (and bs->backing_file is
189*0f62cd82SMax Reitz    # null-co://, because that field actually has not much to do
190*0f62cd82SMax Reitz    # with the header backing filename (except that it is changed by
191*0f62cd82SMax Reitz    # change-backing-file))
192*0f62cd82SMax Reitz
193*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
194*0f62cd82SMax Reitz
195*0f62cd82SMax Reitz    # Detach the backing file by reopening the whole thing
196*0f62cd82SMax Reitz
197*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='node0')
198*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='null')
199*0f62cd82SMax Reitz
200*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
201*0f62cd82SMax Reitz               node_name='node0',
202*0f62cd82SMax Reitz               driver=iotests.imgfmt,
203*0f62cd82SMax Reitz               file={
204*0f62cd82SMax Reitz                   'driver': 'file',
205*0f62cd82SMax Reitz                   'filename': top_img_path
206*0f62cd82SMax Reitz               },
207*0f62cd82SMax Reitz               backing=None,
208*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
209*0f62cd82SMax Reitz
210*0f62cd82SMax Reitz    # Should get a json:{} filename (because we overrode the backing
211*0f62cd82SMax Reitz    # file to not be there)
212*0f62cd82SMax Reitz
213*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
214*0f62cd82SMax Reitz
215*0f62cd82SMax Reitz    # Open the original backing file
216*0f62cd82SMax Reitz
217*0f62cd82SMax Reitz    vm.qmp_log('blockdev-add',
218*0f62cd82SMax Reitz               node_name='original-backing',
219*0f62cd82SMax Reitz               driver=iotests.imgfmt,
220*0f62cd82SMax Reitz               file={
221*0f62cd82SMax Reitz                   'driver': 'file',
222*0f62cd82SMax Reitz                   'filename': base_img_path
223*0f62cd82SMax Reitz               },
224*0f62cd82SMax Reitz               filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
225*0f62cd82SMax Reitz
226*0f62cd82SMax Reitz    # Attach the original backing file to its overlay
227*0f62cd82SMax Reitz
228*0f62cd82SMax Reitz    vm.qmp_log('blockdev-snapshot',
229*0f62cd82SMax Reitz               node='original-backing',
230*0f62cd82SMax Reitz               overlay='node0')
231*0f62cd82SMax Reitz
232*0f62cd82SMax Reitz    # This should give us the original plain result
233*0f62cd82SMax Reitz    # FIXME: Currently, the block layer considers the runtime backing
234*0f62cd82SMax Reitz    #        file to be different from the image header, which is
235*0f62cd82SMax Reitz    #        wrong.  This is fixed by a future patch.
236*0f62cd82SMax Reitz
237*0f62cd82SMax Reitz    log_node_info(vm.node_info('node0'))
238*0f62cd82SMax Reitz
239*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='node0')
240*0f62cd82SMax Reitz    vm.qmp_log('blockdev-del', node_name='original-backing')
241*0f62cd82SMax Reitz
242*0f62cd82SMax Reitz    vm.shutdown()
243