iotests: Make qemu_nbd_popen() a contextmanager

Instead of duplicating the code to wait until the server is ready and
remember to terminate the server and wait for it, make it possible to
use like this:

    with qemu_nbd_popen('-k', sock, image):
        # Access image via qemu-nbd socket...

Only test 264 used this helper, but I had to modify the output since it
did not consistently when starting and stopping qemu-nbd.

Signed-off-by: Nir Soffer <nsoffer@redhat.com>
Message-Id: <20200727215846.395443-3-nsoffer@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Nir Soffer 2020-07-28 00:58:44 +03:00 committed by Eric Blake
parent a2b333c018
commit b7719bcad2
3 changed files with 54 additions and 48 deletions

View file

@ -36,20 +36,8 @@ wait_step = 0.2
qemu_img_create('-f', iotests.imgfmt, disk_a, str(size)) qemu_img_create('-f', iotests.imgfmt, disk_a, str(size))
qemu_img_create('-f', iotests.imgfmt, disk_b, str(size)) qemu_img_create('-f', iotests.imgfmt, disk_b, str(size))
srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b)
# Wait for NBD server availability
t = 0
ok = False
while t < wait_limit:
ok = qemu_io_silent_check('-f', 'raw', '-c', 'read 0 512', nbd_uri)
if ok:
break
time.sleep(wait_step)
t += wait_step
assert ok
with qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b):
vm = iotests.VM().add_drive(disk_a) vm = iotests.VM().add_drive(disk_a)
vm.launch() vm.launch()
vm.hmp_qemu_io('drive0', 'write 0 {}'.format(size)) vm.hmp_qemu_io('drive0', 'write 0 {}'.format(size))
@ -75,10 +63,6 @@ while t < wait_limit:
if jobs and jobs[0]['offset'] > 0: if jobs and jobs[0]['offset'] > 0:
log('Backup job is started') log('Backup job is started')
log('Kill NBD server')
srv.kill()
srv.wait()
jobs = vm.qmp('query-block-jobs')['return'] jobs = vm.qmp('query-block-jobs')['return']
if jobs and jobs[0]['offset'] < jobs[0]['len']: if jobs and jobs[0]['offset'] < jobs[0]['len']:
log('Backup job is still in progress') log('Backup job is still in progress')
@ -88,12 +72,8 @@ vm.qmp_log('block-job-set-speed', device='drive0', speed=0)
# Emulate server down time for 1 second # Emulate server down time for 1 second
time.sleep(1) time.sleep(1)
log('Start NBD server') with qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b):
srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b)
e = vm.event_wait('BLOCK_JOB_COMPLETED') e = vm.event_wait('BLOCK_JOB_COMPLETED')
log('Backup completed: {}'.format(e['data']['offset'])) log('Backup completed: {}'.format(e['data']['offset']))
vm.qmp_log('blockdev-del', node_name='backup0') vm.qmp_log('blockdev-del', node_name='backup0')
srv.kill()
vm.shutdown() vm.shutdown()

View file

@ -1,3 +1,4 @@
Start NBD server
{"execute": "blockdev-add", "arguments": {"driver": "raw", "file": {"driver": "nbd", "reconnect-delay": 10, "server": {"path": "TEST_DIR/PID-nbd-sock", "type": "unix"}}, "node-name": "backup0"}} {"execute": "blockdev-add", "arguments": {"driver": "raw", "file": {"driver": "nbd", "reconnect-delay": 10, "server": {"path": "TEST_DIR/PID-nbd-sock", "type": "unix"}}, "node-name": "backup0"}}
{"return": {}} {"return": {}}
{"execute": "blockdev-backup", "arguments": {"device": "drive0", "speed": 1048576, "sync": "full", "target": "backup0"}} {"execute": "blockdev-backup", "arguments": {"device": "drive0", "speed": 1048576, "sync": "full", "target": "backup0"}}
@ -11,3 +12,4 @@ Start NBD server
Backup completed: 5242880 Backup completed: 5242880
{"execute": "blockdev-del", "arguments": {"node-name": "backup0"}} {"execute": "blockdev-del", "arguments": {"node-name": "backup0"}}
{"return": {}} {"return": {}}
Kill NBD server

View file

@ -28,10 +28,13 @@ import signal
import struct import struct
import subprocess import subprocess
import sys import sys
import time
from typing import (Any, Callable, Dict, Iterable, from typing import (Any, Callable, Dict, Iterable,
List, Optional, Sequence, Tuple, TypeVar) List, Optional, Sequence, Tuple, TypeVar)
import unittest import unittest
from contextlib import contextmanager
# pylint: disable=import-error, wrong-import-position # pylint: disable=import-error, wrong-import-position
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
from qemu import qtest from qemu import qtest
@ -270,9 +273,30 @@ def qemu_nbd_early_pipe(*args):
return subp.returncode, output if subp.returncode else '' return subp.returncode, output if subp.returncode else ''
@contextmanager
def qemu_nbd_popen(*args): def qemu_nbd_popen(*args):
'''Run qemu-nbd in daemon mode and return the parent's exit code''' '''Context manager running qemu-nbd within the context'''
return subprocess.Popen(qemu_nbd_args + ['--persistent'] + list(args)) pid_file = file_path("pid")
cmd = list(qemu_nbd_args)
cmd.extend(('--persistent', '--pid-file', pid_file))
cmd.extend(args)
log('Start NBD server')
p = subprocess.Popen(cmd)
try:
while not os.path.exists(pid_file):
if p.poll() is not None:
raise RuntimeError(
"qemu-nbd terminated with exit code {}: {}"
.format(p.returncode, ' '.join(cmd)))
time.sleep(0.01)
yield
finally:
log('Kill NBD server')
p.kill()
p.wait()
def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
'''Return True if two image files are identical''' '''Return True if two image files are identical'''