mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-03-10 12:56:58 -06:00
In many cases we just want an effect of qmp command and want to raise
on failure. Use vm.cmd() method which does exactly this.
The commit is generated by command
git grep -l '\.qmp(' | xargs ./scripts/python_qmp_updater.py
And then, fix self.assertRaises to expect ExecuteError exception in
tests/qemu-iotests/124
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20231006154125.1068348-16-vsementsov@yandex-team.ru
Signed-off-by: John Snow <jsnow@redhat.com>
132 lines
4.2 KiB
Python
Executable file
132 lines
4.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# group: rw
|
|
#
|
|
# Test graph changes while I/O is happening
|
|
#
|
|
# 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 os
|
|
from threading import Thread
|
|
import iotests
|
|
from iotests import imgfmt, qemu_img, qemu_img_create, qemu_io, \
|
|
QMPTestCase, QemuStorageDaemon
|
|
|
|
|
|
top = os.path.join(iotests.test_dir, 'top.img')
|
|
nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')
|
|
|
|
|
|
def do_qemu_img_bench(count: int = 2000000) -> None:
|
|
"""
|
|
Do some I/O requests on `nbd_sock`.
|
|
"""
|
|
qemu_img('bench', '-f', 'raw', '-c', str(count),
|
|
f'nbd+unix:///node0?socket={nbd_sock}')
|
|
|
|
|
|
class TestGraphChangesWhileIO(QMPTestCase):
|
|
def setUp(self) -> None:
|
|
# Create an overlay that can be added at runtime on top of the
|
|
# null-co block node that will receive I/O
|
|
qemu_img_create('-f', imgfmt, '-F', 'raw', '-b', 'null-co://', top)
|
|
|
|
# QSD instance with a null-co block node in an I/O thread,
|
|
# exported over NBD (on `nbd_sock`, export name "node0")
|
|
self.qsd = QemuStorageDaemon(
|
|
'--object', 'iothread,id=iothread0',
|
|
'--blockdev', 'null-co,node-name=node0,read-zeroes=true',
|
|
'--nbd-server', f'addr.type=unix,addr.path={nbd_sock}',
|
|
'--export', 'nbd,id=exp0,node-name=node0,iothread=iothread0,' +
|
|
'fixed-iothread=true,writable=true',
|
|
qmp=True
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.qsd.stop()
|
|
|
|
def test_blockdev_add_while_io(self) -> None:
|
|
# Run qemu-img bench in the background
|
|
bench_thr = Thread(target=do_qemu_img_bench)
|
|
bench_thr.start()
|
|
|
|
# While qemu-img bench is running, repeatedly add and remove an
|
|
# overlay to/from node0
|
|
while bench_thr.is_alive():
|
|
self.qsd.cmd('blockdev-add', {
|
|
'driver': imgfmt,
|
|
'node-name': 'overlay',
|
|
'backing': 'node0',
|
|
'file': {
|
|
'driver': 'file',
|
|
'filename': top
|
|
}
|
|
})
|
|
|
|
self.qsd.cmd('blockdev-del', {
|
|
'node-name': 'overlay'
|
|
})
|
|
|
|
bench_thr.join()
|
|
|
|
def test_commit_while_io(self) -> None:
|
|
# Run qemu-img bench in the background
|
|
bench_thr = Thread(target=do_qemu_img_bench, args=(200000, ))
|
|
bench_thr.start()
|
|
|
|
qemu_io('-c', 'write 0 64k', top)
|
|
qemu_io('-c', 'write 128k 64k', top)
|
|
|
|
self.qsd.cmd('blockdev-add', {
|
|
'driver': imgfmt,
|
|
'node-name': 'overlay',
|
|
'backing': None,
|
|
'file': {
|
|
'driver': 'file',
|
|
'filename': top
|
|
}
|
|
})
|
|
|
|
self.qsd.cmd('blockdev-snapshot', {
|
|
'node': 'node0',
|
|
'overlay': 'overlay',
|
|
})
|
|
|
|
# While qemu-img bench is running, repeatedly commit overlay to node0
|
|
while bench_thr.is_alive():
|
|
self.qsd.cmd('block-commit', {
|
|
'job-id': 'job0',
|
|
'device': 'overlay',
|
|
})
|
|
|
|
self.qsd.cmd('block-job-cancel', {
|
|
'device': 'job0',
|
|
})
|
|
|
|
cancelled = False
|
|
while not cancelled:
|
|
for event in self.qsd.get_qmp().get_events(wait=10.0):
|
|
if event['event'] != 'JOB_STATUS_CHANGE':
|
|
continue
|
|
if event['data']['status'] == 'null':
|
|
cancelled = True
|
|
|
|
bench_thr.join()
|
|
|
|
if __name__ == '__main__':
|
|
# Format must support raw backing files
|
|
iotests.main(supported_fmts=['qcow', 'qcow2', 'qed'],
|
|
supported_protocols=['file'])
|