iotests/backing-file-invalidation: Add new test
Add a new test to see what happens when you migrate a VM with a backing chain that has json:{} backing file strings, which, when opened, will be resolved to plain filenames. Signed-off-by: Hanna Reitz <hreitz@redhat.com> Message-Id: <20220803144446.20723-4-hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
dc70638ff6
commit
283153f10a
152
tests/qemu-iotests/tests/backing-file-invalidation
Executable file
152
tests/qemu-iotests/tests/backing-file-invalidation
Executable file
@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
# group: rw migration
|
||||
#
|
||||
# Migrate a VM with a BDS with backing nodes, which runs
|
||||
# bdrv_invalidate_cache(), which for qcow2 and qed triggers reading the
|
||||
# backing file string from the image header. Check whether this
|
||||
# interferes with bdrv_backing_overridden().
|
||||
#
|
||||
# Copyright (C) 2022 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/>.
|
||||
#
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
import iotests
|
||||
from iotests import qemu_img_create, qemu_img_info
|
||||
|
||||
|
||||
image_size = 1 * 1024 * 1024
|
||||
imgs = [os.path.join(iotests.test_dir, f'{i}.img') for i in range(0, 4)]
|
||||
|
||||
mig_sock = os.path.join(iotests.sock_dir, 'mig.sock')
|
||||
|
||||
|
||||
class TestPostMigrateFilename(iotests.QMPTestCase):
|
||||
vm_s: Optional[iotests.VM] = None
|
||||
vm_d: Optional[iotests.VM] = None
|
||||
|
||||
def setUp(self) -> None:
|
||||
# Create backing chain of three images, where the backing file strings
|
||||
# are json:{} filenames
|
||||
qemu_img_create('-f', iotests.imgfmt, imgs[0], str(image_size))
|
||||
for i in range(1, 3):
|
||||
backing = {
|
||||
'driver': iotests.imgfmt,
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': imgs[i - 1]
|
||||
}
|
||||
}
|
||||
qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
|
||||
'-b', 'json:' + json.dumps(backing),
|
||||
imgs[i], str(image_size))
|
||||
|
||||
def tearDown(self) -> None:
|
||||
if self.vm_s is not None:
|
||||
self.vm_s.shutdown()
|
||||
if self.vm_d is not None:
|
||||
self.vm_d.shutdown()
|
||||
|
||||
for img in imgs:
|
||||
try:
|
||||
os.remove(img)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
os.remove(mig_sock)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def test_migration(self) -> None:
|
||||
"""
|
||||
Migrate a VM with the backing chain created in setUp() attached. At
|
||||
the end of the migration process, the destination will run
|
||||
bdrv_invalidate_cache(), which for some image formats (qcow2 and qed)
|
||||
means the backing file string is re-read from the image header. If
|
||||
this overwrites bs->auto_backing_file, doing so may cause
|
||||
bdrv_backing_overridden() to become true: The image header reports a
|
||||
json:{} filename, but when opening it, bdrv_refresh_filename() will
|
||||
simplify it to a plain simple filename; and when bs->auto_backing_file
|
||||
and bs->backing->bs->filename differ, bdrv_backing_overridden() becomes
|
||||
true.
|
||||
If bdrv_backing_overridden() is true, the BDS will be forced to get a
|
||||
json:{} filename, which in general is not the end of the world, but not
|
||||
great. Check whether that happens, i.e. whether migration changes the
|
||||
node's filename.
|
||||
"""
|
||||
|
||||
blockdev = {
|
||||
'node-name': 'node0',
|
||||
'driver': iotests.imgfmt,
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': imgs[2]
|
||||
}
|
||||
}
|
||||
|
||||
self.vm_s = iotests.VM(path_suffix='a') \
|
||||
.add_blockdev(json.dumps(blockdev))
|
||||
self.vm_d = iotests.VM(path_suffix='b') \
|
||||
.add_blockdev(json.dumps(blockdev)) \
|
||||
.add_incoming(f'unix:{mig_sock}')
|
||||
|
||||
assert self.vm_s is not None
|
||||
assert self.vm_d is not None
|
||||
|
||||
self.vm_s.launch()
|
||||
self.vm_d.launch()
|
||||
|
||||
pre_mig_filename = self.vm_s.node_info('node0')['file']
|
||||
|
||||
self.vm_s.qmp('migrate', uri=f'unix:{mig_sock}')
|
||||
|
||||
# Wait for migration to be done
|
||||
self.vm_s.event_wait('STOP')
|
||||
self.vm_d.event_wait('RESUME')
|
||||
|
||||
post_mig_filename = self.vm_d.node_info('node0')['file']
|
||||
|
||||
# Verify that the filename hasn't changed from before the migration
|
||||
self.assertEqual(pre_mig_filename, post_mig_filename)
|
||||
|
||||
self.vm_s.shutdown()
|
||||
self.vm_s = None
|
||||
|
||||
# For good measure, try creating an overlay and check its backing
|
||||
# chain below. This is how the issue was originally found.
|
||||
result = self.vm_d.qmp('blockdev-snapshot-sync',
|
||||
format=iotests.imgfmt,
|
||||
snapshot_file=imgs[3],
|
||||
node_name='node0',
|
||||
snapshot_node_name='node0-overlay')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
self.vm_d.shutdown()
|
||||
self.vm_d = None
|
||||
|
||||
# Check the newly created overlay's backing chain
|
||||
chain = qemu_img_info('--backing-chain', imgs[3])
|
||||
for index, image in enumerate(chain):
|
||||
self.assertEqual(image['filename'], imgs[3 - index])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# These are the image formats that run their open() function from their
|
||||
# .bdrv_co_invaliate_cache() implementations, so test them
|
||||
iotests.main(supported_fmts=['qcow2', 'qed'],
|
||||
supported_protocols=['file'])
|
5
tests/qemu-iotests/tests/backing-file-invalidation.out
Normal file
5
tests/qemu-iotests/tests/backing-file-invalidation.out
Normal file
@ -0,0 +1,5 @@
|
||||
.
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 tests
|
||||
|
||||
OK
|
Loading…
Reference in New Issue
Block a user