mirror of
https://github.com/xemu-project/xemu.git
synced 2024-06-02 20:18:25 -04:00
37094b6dd5
Now that we are fully switched over to the new QMP library, move it back over the old namespace. This is being done primarily so that we may upload this package simply as "qemu.qmp" without introducing confusion over whether or not "aqmp" is a new protocol or not. The trade-off is increased confusion inside the QEMU developer tree. Sorry! Note: the 'private' member "_aqmp" in legacy.py also changes to "_qmp"; not out of necessity, but just to remove any traces of the "aqmp" name. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Beraldo Leal <bleal@redhat.com> Acked-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org> Message-id: 20220330172812.3427355-8-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
122 lines
4.6 KiB
Python
Executable file
122 lines
4.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# group: rw
|
|
#
|
|
# Test permissions taken by the mirror-top filter
|
|
#
|
|
# Copyright (C) 2021 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 os
|
|
|
|
from qemu.machine import machine
|
|
|
|
import iotests
|
|
from iotests import change_log_level, qemu_img
|
|
|
|
|
|
image_size = 1 * 1024 * 1024
|
|
source = os.path.join(iotests.test_dir, 'source.img')
|
|
|
|
|
|
class TestMirrorTopPerms(iotests.QMPTestCase):
|
|
def setUp(self):
|
|
qemu_img('create', '-f', iotests.imgfmt, source, str(image_size))
|
|
self.vm = iotests.VM()
|
|
self.vm.add_drive(source)
|
|
self.vm.add_blockdev(f'null-co,node-name=null,size={image_size}')
|
|
self.vm.launch()
|
|
|
|
# Will be created by the test function itself
|
|
self.vm_b = None
|
|
|
|
def tearDown(self):
|
|
try:
|
|
self.vm.shutdown()
|
|
except machine.AbnormalShutdown:
|
|
pass
|
|
|
|
if self.vm_b is not None:
|
|
self.vm_b.shutdown()
|
|
|
|
os.remove(source)
|
|
|
|
def test_cancel(self):
|
|
"""
|
|
Before commit 53431b9086b28, mirror-top used to not take any
|
|
permissions but WRITE and share all permissions. Because it
|
|
is inserted between the source's original parents and the
|
|
source, there generally was no parent that would have taken or
|
|
unshared any permissions on the source, which means that an
|
|
external process could access the image unhindered by locks.
|
|
(Unless there was a parent above the protocol node that would
|
|
take its own locks, e.g. a format driver.)
|
|
This is bad enough, but if the mirror job is then cancelled,
|
|
the mirroring VM tries to take back the image, restores the
|
|
original permissions taken and unshared, and assumes this must
|
|
just work. But it will not, and so the VM aborts.
|
|
|
|
Commit 53431b9086b28 made mirror keep the original permissions
|
|
and so no other process can "steal" the image.
|
|
|
|
(Note that you cannot really do the same with the target image
|
|
and then completing the job, because the mirror job always
|
|
took/unshared the correct permissions on the target. For
|
|
example, it does not share READ_CONSISTENT, which makes it
|
|
difficult to let some other qemu process open the image.)
|
|
"""
|
|
|
|
result = self.vm.qmp('blockdev-mirror',
|
|
job_id='mirror',
|
|
device='drive0',
|
|
target='null',
|
|
sync='full')
|
|
self.assert_qmp(result, 'return', {})
|
|
|
|
self.vm.event_wait('BLOCK_JOB_READY')
|
|
|
|
# We want this to fail because the image cannot be locked.
|
|
# If it does not fail, continue still and see what happens.
|
|
self.vm_b = iotests.VM(path_suffix='b')
|
|
# Must use -blockdev -device so we can use share-rw.
|
|
# (And we need share-rw=on because mirror-top was always
|
|
# forced to take the WRITE permission so it can write to the
|
|
# source image.)
|
|
self.vm_b.add_blockdev(f'file,node-name=drive0,filename={source}')
|
|
self.vm_b.add_device('virtio-blk,drive=drive0,share-rw=on')
|
|
try:
|
|
# Silence QMP logging errors temporarily.
|
|
with change_log_level('qemu.qmp'):
|
|
self.vm_b.launch()
|
|
print('ERROR: VM B launched successfully, '
|
|
'this should not have happened')
|
|
except machine.VMLaunchFailure as exc:
|
|
assert 'Is another process using the image' in exc.output
|
|
|
|
result = self.vm.qmp('block-job-cancel',
|
|
device='mirror')
|
|
self.assert_qmp(result, 'return', {})
|
|
|
|
self.vm.event_wait('BLOCK_JOB_COMPLETED')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# No metadata format driver supported, because they would for
|
|
# example always unshare the WRITE permission. The raw driver
|
|
# just passes through the permissions from the guest device, and
|
|
# those are the permissions that we want to test.
|
|
iotests.main(supported_fmts=['raw'],
|
|
supported_protocols=['file'])
|