From 0f3231bfb5a9b83895bad52a0c538818f0a8bd6c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 18 Sep 2020 17:35:14 +0200 Subject: tests/check-block: Do not run the iotests with old versions of bash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS is shipped with a very old version of the bash (3.2), which is currently not suitable for running the iotests anymore (e.g. it is missing support for "readarray" which is used in the file tests/qemu-iotests/common.filter). Add a check to skip the iotests in this case - if someone still wants to run the iotests on macOS, they can install a newer version from homebrew, for example. Signed-off-by: Thomas Huth Message-Id: <20200918153514.330705-1-thuth@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Kevin Wolf --- tests/check-block.sh | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tests') diff --git a/tests/check-block.sh b/tests/check-block.sh index a5a6906..f6b1bda 100755 --- a/tests/check-block.sh +++ b/tests/check-block.sh @@ -46,6 +46,11 @@ if ! command -v bash >/dev/null 2>&1 ; then exit 0 fi +if LANG=C bash --version | grep -q 'GNU bash, version [123]' ; then + echo "bash version too old ==> Not running the qemu-iotests." + exit 0 +fi + if ! (sed --version | grep 'GNU sed') > /dev/null 2>&1 ; then if ! command -v gsed >/dev/null 2>&1; then echo "GNU sed not available ==> Not running the qemu-iotests." -- cgit v1.1 From d53be9ce55a38e430b88985f637f696bf99cbf0b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:04 +0200 Subject: block/export: Add 'id' option to block-export-add We'll need an id to identify block exports in monitor commands. This adds one. Note that this is different from the 'name' option in the NBD server, which is the externally visible export name. While block export ids need to be unique in the whole process, export names must be unique only for the same server. Different export types or (potentially in the future) multiple NBD servers can have the same export name externally, but still need different block export ids internally. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Message-Id: <20200924152717.287415-19-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- tests/qemu-iotests/223.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index e1eaaed..31ce9e6 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -45,7 +45,7 @@ exports available: 0 {"execute":"nbd-server-add", "arguments":{"device":"nosuch"}} {"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}} {"execute":"nbd-server-add", "arguments":{"device":"n"}} -{"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}} +{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}} {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}} @@ -126,7 +126,7 @@ exports available: 0 {"execute":"nbd-server-add", "arguments":{"device":"nosuch"}} {"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}} {"execute":"nbd-server-add", "arguments":{"device":"n"}} -{"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}} +{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}} {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}} -- cgit v1.1 From 1a9f7a804f52caee6bc6769a8bb0a018e6c8ec81 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:07 +0200 Subject: block/export: Add BLOCK_EXPORT_DELETED event Clients may want to know when an export has finally disappeard (block-export-del returns earlier than that in the general case), so add a QAPI event for it. Signed-off-by: Kevin Wolf Message-Id: <20200924152717.287415-22-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/140 | 9 ++++++++- tests/qemu-iotests/140.out | 2 +- tests/qemu-iotests/223.out | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140 index 8d2ce5d..309b177 100755 --- a/tests/qemu-iotests/140 +++ b/tests/qemu-iotests/140 @@ -81,10 +81,17 @@ $QEMU_IO_PROG -f raw -r -c 'read -P 42 0 64k' \ "nbd+unix:///drv?socket=$SOCK_DIR/nbd" 2>&1 \ | _filter_qemu_io | _filter_nbd +# The order of 'return' and the BLOCK_EXPORT_DELETED event is undefined. Just +# wait until we've twice seen one of them. Filter the 'return' line out so that +# the output is defined. _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'eject', 'arguments': { 'device': 'drv' }}" \ - 'return' + 'return\|BLOCK_EXPORT_DELETED' | + grep -v 'return' + +_send_qemu_cmd $QEMU_HANDLE '' 'return\|BLOCK_EXPORT_DELETED' | + grep -v 'return' $QEMU_IO_PROG -f raw -r -c close \ "nbd+unix:///drv?socket=$SOCK_DIR/nbd" 2>&1 \ diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out index 86b985d..62d9c3a 100644 --- a/tests/qemu-iotests/140.out +++ b/tests/qemu-iotests/140.out @@ -11,7 +11,7 @@ wrote 65536/65536 bytes at offset 0 read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'eject', 'arguments': { 'device': 'drv' }} -{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "drv"}} qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'drv' not present { 'execute': 'quit' } diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index 31ce9e6..f6eac23 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -102,8 +102,10 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"return": {}} @@ -183,8 +185,10 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"return": {}} -- cgit v1.1 From 91efbae93887a2b80e2979d8b8a169302cf927d1 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:14 +0200 Subject: iotests: Factor out qemu_tool_pipe_and_status() We have three almost identical functions that call an external process and return its output and return code. Refactor them into small wrappers around a common function. Signed-off-by: Kevin Wolf Message-Id: <20200924152717.287415-29-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/iotests.py | 49 ++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index f484604..f7ad0c1 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -88,21 +88,30 @@ luks_default_secret_object = 'secret,id=keysec0,data=' + \ luks_default_key_secret_opt = 'key-secret=keysec0' -def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]: +def qemu_tool_pipe_and_status(tool: str, args: Sequence[str], + connect_stderr: bool = True) -> Tuple[str, int]: """ - Run qemu-img and return both its output and its exit code + Run a tool and return both its output and its exit code """ - subp = subprocess.Popen(qemu_img_args + list(args), + stderr = subprocess.STDOUT if connect_stderr else None + subp = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, + stderr=stderr, universal_newlines=True) output = subp.communicate()[0] if subp.returncode < 0: - sys.stderr.write('qemu-img received signal %i: %s\n' - % (-subp.returncode, + sys.stderr.write('%s received signal %i: %s\n' + % (tool, -subp.returncode, ' '.join(qemu_img_args + list(args)))) return (output, subp.returncode) +def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]: + """ + Run qemu-img and return both its output and its exit code + """ + full_args = qemu_img_args + list(args) + return qemu_tool_pipe_and_status('qemu-img', full_args) + def qemu_img(*args: str) -> int: '''Run qemu-img and return the exit code''' return qemu_img_pipe_and_status(*args)[1] @@ -263,19 +272,13 @@ def qemu_nbd(*args): '''Run qemu-nbd in daemon mode and return the parent's exit code''' return subprocess.call(qemu_nbd_args + ['--fork'] + list(args)) -def qemu_nbd_early_pipe(*args): +def qemu_nbd_early_pipe(*args: str) -> Tuple[int, str]: '''Run qemu-nbd in daemon mode and return both the parent's exit code and its output in case of an error''' - subp = subprocess.Popen(qemu_nbd_args + ['--fork'] + list(args), - stdout=subprocess.PIPE, - universal_newlines=True) - output = subp.communicate()[0] - if subp.returncode < 0: - sys.stderr.write('qemu-nbd received signal %i: %s\n' % - (-subp.returncode, - ' '.join(qemu_nbd_args + ['--fork'] + list(args)))) - - return subp.returncode, output if subp.returncode else '' + full_args = qemu_nbd_args + ['--fork'] + list(args) + output, returncode = qemu_tool_pipe_and_status('qemu-nbd', full_args, + connect_stderr=False) + return returncode, output if returncode else '' @contextmanager def qemu_nbd_popen(*args): @@ -1141,20 +1144,14 @@ def verify_working_luks(): if not working: notrun(reason) -def qemu_pipe(*args): +def qemu_pipe(*args: str) -> str: """ Run qemu with an option to print something and exit (e.g. a help option). :return: QEMU's stdout output. """ - args = [qemu_prog] + qemu_opts + list(args) - subp = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - output = subp.communicate()[0] - if subp.returncode < 0: - sys.stderr.write('qemu received signal %i: %s\n' % - (-subp.returncode, ' '.join(args))) + full_args = [qemu_prog] + qemu_opts + list(args) + output, _ = qemu_tool_pipe_and_status('qemu', full_args) return output def supported_formats(read_only=False): -- cgit v1.1 From 81b6b2bc1af5b651e4cc659b0dbbf9626fbc227c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:15 +0200 Subject: iotests: Introduce qemu_nbd_list_log() Add a function to list the NBD exports offered by an NBD server. Signed-off-by: Kevin Wolf Message-Id: <20200924152717.287415-30-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/iotests.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index f7ad0c1..9695c91 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -65,7 +65,8 @@ if os.environ.get('QEMU_IO_OPTIONS_NO_FMT'): qemu_io_args_no_fmt += \ os.environ['QEMU_IO_OPTIONS_NO_FMT'].strip().split(' ') -qemu_nbd_args = [os.environ.get('QEMU_NBD_PROG', 'qemu-nbd')] +qemu_nbd_prog = os.environ.get('QEMU_NBD_PROG', 'qemu-nbd') +qemu_nbd_args = [qemu_nbd_prog] if os.environ.get('QEMU_NBD_OPTIONS'): qemu_nbd_args += os.environ['QEMU_NBD_OPTIONS'].strip().split(' ') @@ -280,6 +281,13 @@ def qemu_nbd_early_pipe(*args: str) -> Tuple[int, str]: connect_stderr=False) return returncode, output if returncode else '' +def qemu_nbd_list_log(*args: str) -> str: + '''Run qemu-nbd to list remote exports''' + full_args = [qemu_nbd_prog, '-L'] + list(args) + output, _ = qemu_tool_pipe_and_status('qemu-nbd', full_args) + log(output, filters=[filter_testfiles, filter_nbd_exports]) + return output + @contextmanager def qemu_nbd_popen(*args): '''Context manager running qemu-nbd within the context''' @@ -413,6 +421,9 @@ def filter_qmp_imgfmt(qmsg): return value return filter_qmp(qmsg, _filter) +def filter_nbd_exports(output: str) -> str: + return re.sub(r'((min|opt|max) block): [0-9]+', r'\1: XXX', output) + Msg = TypeVar('Msg', Dict[str, Any], List[Any], str) -- cgit v1.1 From f71255228e7a906511c8d862c076cd184069d28c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:16 +0200 Subject: iotests: Allow supported and unsupported formats at the same time This is useful for specifying 'generic' as supported (which includes only writable image formats), but still excluding some incompatible writable formats. It also removes more lines than it adds. Signed-off-by: Kevin Wolf Message-Id: <20200924152717.287415-31-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/iotests.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 9695c91..f212cec 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -1062,16 +1062,12 @@ def case_notrun(reason): def _verify_image_format(supported_fmts: Sequence[str] = (), unsupported_fmts: Sequence[str] = ()) -> None: - assert not (supported_fmts and unsupported_fmts) - if 'generic' in supported_fmts and \ os.environ.get('IMGFMT_GENERIC', 'true') == 'true': # similar to # _supported_fmt generic # for bash tests - if imgfmt == 'luks': - verify_working_luks() - return + supported_fmts = () not_sup = supported_fmts and (imgfmt not in supported_fmts) if not_sup or (imgfmt in unsupported_fmts): -- cgit v1.1 From f51af04cce148e825a9f3c4f446e5cd3cfaff71d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 Sep 2020 17:27:17 +0200 Subject: iotests: Test block-export-* QMP interface Signed-off-by: Kevin Wolf Message-Id: <20200924152717.287415-32-kwolf@redhat.com> Acked-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf --- tests/qemu-iotests/307 | 132 +++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/307.out | 124 ++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 257 insertions(+) create mode 100755 tests/qemu-iotests/307 create mode 100644 tests/qemu-iotests/307.out (limited to 'tests') diff --git a/tests/qemu-iotests/307 b/tests/qemu-iotests/307 new file mode 100755 index 0000000..de7c25f --- /dev/null +++ b/tests/qemu-iotests/307 @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 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 . +# +# Creator/Owner: Kevin Wolf +# +# Test the block export QAPI interfaces + +import iotests +import os + +# Need a writable image format (but not vpc, which rounds the image size, nor +# luks which requires special command lines) +iotests.script_initialize( + supported_fmts=['generic'], + unsupported_fmts=['luks', 'vpc'], + supported_platforms=['linux'], +) + +with iotests.FilePath('image') as img, \ + iotests.FilePath('socket', base_dir=iotests.sock_dir) as socket, \ + iotests.VM() as vm: + + iotests.qemu_img('create', '-f', iotests.imgfmt, img, '64M') + iotests.qemu_io_log('-f', iotests.imgfmt, '-c', 'write -P 0x11 0 4k', img) + + iotests.log('=== Launch VM ===') + + virtio_scsi_device = iotests.get_virtio_scsi_device() + + vm.add_object('iothread,id=iothread0') + vm.add_blockdev(f'file,filename={img},node-name=file') + vm.add_blockdev(f'{iotests.imgfmt},file=file,node-name=fmt') + vm.add_blockdev('raw,file=file,node-name=ro,read-only=on') + vm.add_device(f'id=scsi0,driver={virtio_scsi_device},iothread=iothread0') + vm.launch() + + vm.qmp_log('nbd-server-start', + addr={'type': 'unix', 'data': {'path': socket}}, + filters=(iotests.filter_qmp_testfiles, )) + vm.qmp_log('query-block-exports') + + iotests.log('\n=== Create a read-only NBD export ===') + + vm.qmp_log('block-export-add', id='export0', type='nbd', node_name='fmt') + vm.qmp_log('query-block-exports') + + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Try a few invalid things ===') + + vm.qmp_log('block-export-add', id='#invalid', type='nbd', node_name='fmt') + vm.qmp_log('block-export-add', id='export0', type='nbd', node_name='fmt') + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='ro', + writable=True) + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('query-block-exports') + + iotests.log('\n=== Move export to an iothread ===') + + vm.qmp_log('device_add', id='sda', driver='scsi-hd', drive='fmt') + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Add a writable export ===') + + # This fails because share-rw=off + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='fmt', + name='export1', writable=True, writethrough=True, + description='This is the writable second export') + + vm.qmp_log('device_del', id='sda') + event = vm.event_wait(name="DEVICE_DELETED", + match={'data': {'device': 'sda'}}) + iotests.log(event, filters=[iotests.filter_qmp_event]) + vm.qmp_log('device_add', id='sda', driver='scsi-hd', drive='fmt', + share_rw=True) + + # Now it should work + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='fmt', + name='export1', writable=True, writethrough=True, + description='This is the writable second export') + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Connect qemu-io to export1, try removing exports ===') + + nbd_url = f'nbd+unix:///export1?socket={socket}' + qemu_io = iotests.QemuIoInteractive('-f', 'raw', nbd_url) + + iotests.log(qemu_io.cmd('read -P 0x11 0 4k'), + filters=[iotests.filter_qemu_io]) + iotests.log(qemu_io.cmd('write -P 0x22 4k 4k'), + filters=[iotests.filter_qemu_io]) + + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('block-export-del', id='export0') + iotests.log(vm.get_qmp_events_filtered()) + qemu_io.close() + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Connect qemu-io again, try force removing ===') + + qemu_io = iotests.QemuIoInteractive('-f', 'raw', nbd_url) + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('block-export-del', id='export1', mode='hard') + + # This should fail now + iotests.log(qemu_io.cmd('read -P 0x11 0 4k')) + qemu_io.close() + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Shut down QEMU ===') + vm.shutdown() diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out new file mode 100644 index 0000000..daa8ad2 --- /dev/null +++ b/tests/qemu-iotests/307.out @@ -0,0 +1,124 @@ +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Launch VM === +{"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-socket"}, "type": "unix"}}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": []} + +=== Create a read-only NBD export === +{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Try a few invalid things === +{"execute": "block-export-add", "arguments": {"id": "#invalid", "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "Invalid block export id"}} +{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "Block export id 'export0' is already in use"}} +{"execute": "block-export-add", "arguments": {"id": "export1", "node-name": "ro", "type": "nbd", "writable": true}} +{"error": {"class": "GenericError", "desc": "Cannot export read-only node as writable"}} +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "Export 'export1' is not found"}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} + +=== Move export to an iothread === +{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda"}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Add a writable export === +{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}} +{"error": {"class": "GenericError", "desc": "Conflicts with use by sda as 'root', which does not allow 'write' on fmt"}} +{"execute": "device_del", "arguments": {"id": "sda"}} +{"return": {}} +{"data": {"device": "sda", "path": "/machine/peripheral/sda"}, "event": "DEVICE_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda", "share-rw": true}} +{"return": {}} +{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}, {"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 2 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + export: 'export1' + description: This is the writable second export + size: 67108864 + flags: 0xced ( flush fua trim zeroes df cache fast-zero ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Connect qemu-io to export1, try removing exports === +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 4096/4096 bytes at offset 4096 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}} +{"execute": "block-export-del", "arguments": {"id": "export0"}} +{"return": {}} +[{"data": {"id": "export0"}, "event": "BLOCK_EXPORT_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}] +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'export1' + description: This is the writable second export + size: 67108864 + flags: 0xced ( flush fua trim zeroes df cache fast-zero ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Connect qemu-io again, try force removing === +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}} +{"execute": "block-export-del", "arguments": {"id": "export1", "mode": "hard"}} +{"return": {}} +read failed: Input/output error + +{"execute": "query-block-exports", "arguments": {}} +{"return": []} +exports available: 0 + + +=== Shut down QEMU === diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ff59cfd..9e4f7c0 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -314,3 +314,4 @@ 303 rw quick 304 rw quick 305 rw quick +307 rw quick export -- cgit v1.1