[PATCH nbdinfo proposal] info: Add a --map option for displaying allocation metadata
by Richard W.M. Jones
This is a rough-and-ready implementation of nbdinfo --map option, to
display the allocation and other metadata of NBD exports. I only
tested it lightly against nbdkit. It needs at least some tests.
Command like these should work:
nbdinfo --map nbd://localhost
nbdinfo --map=qemu:dirty-bitmap nbd://localhost
Rich.
4 years, 3 months
[v2v PATCH 1/3] linux: remove warning for packages with no files
by Pino Toscano
Metapackages are valid packages with no files, used to easily install
something without manually installing bits.
This is the case of the "kernel" package in Fedora/RHEL/etc in the last
couple of years.
---
v2v/linux_kernels.ml | 1 -
1 file changed, 1 deletion(-)
diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml
index 9a41225a..78c1ee59 100644
--- a/v2v/linux_kernels.ml
+++ b/v2v/linux_kernels.ml
@@ -107,7 +107,6 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
let files = Linux.file_list_of_package g inspect app in
if files = [] then (
- warning (f_"package ‘%s’ contains no files") name;
None
)
else (
--
2.26.2
4 years, 3 months
[libnbd PATCH v2] nbdsh: Catch nbd.Error from -c arguments
by Eric Blake
When using nbdsh for scripting, it is convenient to let nbdsh fail
with status 1 when encountering an API failure. However, doing so by
letting the nbd.Error exception leak all the way causes ABRT (at least
on Fedora 32 with abrt-python3-handler installed) to assume the
program crashed from a programming error, and needlessly complicates
clients to have to add try: blocks. Better is if nbdsh itself handles
the problem, and only prints a stack trace when debugging is in
effect, but otherwise just prints the error message. In this way, the
user is not presented with a wall of python stack trace, and ABRT does
not think that the exception was unhandled.
See https://github.com/libguestfs/nbdkit/commit/e13048fd9 for an
example of client cleanup made more verbose if we don't patch libnbd.
---
On IRC, we decided that printing the stack trace can be useful when
debugging (if -c triggers calls through some deeply-nested python
code), but generally gets in the way for default behavior.
python/nbdsh.py | 20 ++++++++++++++++----
sh/test-error.sh | 23 ++++++++++++++++++++++-
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/python/nbdsh.py b/python/nbdsh.py
index 61d38e8..9ed2938 100644
--- a/python/nbdsh.py
+++ b/python/nbdsh.py
@@ -16,6 +16,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+import os
+import traceback
+
+
# The NBD shell.
def shell():
import argparse
@@ -100,8 +104,16 @@ help(nbd) # Display documentation
else:
# https://stackoverflow.com/a/11754346
d = dict(locals(), **globals())
- for c in args.command:
- if c != '-':
- exec(c, d, d)
+ try:
+ for c in args.command:
+ if c != '-':
+ exec(c, d, d)
+ else:
+ exec(sys.stdin.read(), d, d)
+ except nbd.Error as ex:
+ if os.environ.get("LIBNBD_DEBUG", "0") == "1":
+ traceback.print_exc()
else:
- exec(sys.stdin.read(), d, d)
+ print("nbdsh: command line script failed: %s" % ex.string,
+ file=sys.stderr)
+ sys.exit(1)
diff --git a/sh/test-error.sh b/sh/test-error.sh
index c6ab474..a33ce47 100755
--- a/sh/test-error.sh
+++ b/sh/test-error.sh
@@ -40,6 +40,27 @@ nbdsh -u 'nbd+unix:///?socket=/nosuchsock' >$out 2>$err && fail=1
test ! -s $out
cat $err
grep Traceback $err && fail=1
-grep '^nbdsh: unable to connect to uri.*nosuchsock' test-error.err
+grep '^nbdsh: unable to connect to uri.*nosuchsock' $err
+
+# Triggering nbd.Error non-interactively (via -c) prints the error. The
+# output includes the python trace when debugging is enabled (which is
+# the default for our testsuite, when using ./run).
+nbdsh -c 'h.is_read_only()' >$out 2>$err && fail=1
+test ! -s $out
+cat $err
+grep Traceback $err
+grep 'in is_read_only' $err
+grep '^nbd\.Error: nbd_is_read_only: ' $err
+
+# Override ./run's default to show that without debug, the error is succinct.
+nbdsh -c '
+import os
+os.environ["LIBNBD_DEBUG"] = "0"
+h.is_read_only()
+' >$out 2>$err && fail=1
+test ! -s $out
+cat $err
+grep Traceback $err && fail=1
+grep '^nbdsh: command line script failed: nbd_is_read_only: ' $err
exit $fail
--
2.28.0
4 years, 3 months
[v2v PATCH 1/2] linux: split kernel packages filtering from processing
by Pino Toscano
Split the processing of the kernel packages in two phases:
- filtering only (by name)
- actual processing
This makes the filtering part easier to review/modify, and it is now
much easier to see (in the debug log) which packages are processed as
kernel packages.
There are no behaviour changes (other than an additional debug message).
---
v2v/linux_kernels.ml | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml
index 1bc10948..dc0c285d 100644
--- a/v2v/linux_kernels.ml
+++ b/v2v/linux_kernels.ml
@@ -89,11 +89,19 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
PCRE.compile "^initrd.img-.*$"
else
PCRE.compile "^initr(?:d|amfs)-.*(?:\\.img)?$" in
+ let kernel_pkgs = List.filter (
+ fun { G.app2_name = name } ->
+ name = "kernel"
+ || String.is_prefix name "kernel-"
+ || String.is_prefix name "linux-image-"
+ ) inspect.i_apps in
+ if verbose () then (
+ let names = List.map (fun { G.app2_name = name } -> name) kernel_pkgs in
+ eprintf "candidate kernel packages in this guest: %s%!\n"
+ (String.concat " " names)
+ );
List.filter_map (
- function
- | { G.app2_name = name } as app
- when name = "kernel" || String.is_prefix name "kernel-"
- || String.is_prefix name "linux-image-" ->
+ fun ({ G.app2_name = name } as app) ->
(try
(* For each kernel, list the files directly owned by the kernel. *)
let files = Linux.file_list_of_package g inspect app in
@@ -277,9 +285,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
with Not_found -> None
)
-
- | _ -> None
- ) inspect.i_apps in
+ ) kernel_pkgs in
if verbose () then (
eprintf "installed kernel packages in this guest:\n";
--
2.26.2
4 years, 3 months
[PATCH] build: fix includedir in uninstalled libguestfs.pc
by Pino Toscano
Update includedir with the new directory that contains guestfs.h.
Updates commit 75abec1f706e555cd6c9915be03c732b56a94596.
---
lib/local/libguestfs.pc.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/local/libguestfs.pc.in b/lib/local/libguestfs.pc.in
index 129682be8..46cef1e16 100644
--- a/lib/local/libguestfs.pc.in
+++ b/lib/local/libguestfs.pc.in
@@ -26,7 +26,7 @@
prefix=@abs_top_builddir@
exec_prefix=@abs_top_builddir@
libdir=@abs_top_builddir(a)/lib/.libs
-includedir=@abs_top_srcdir@/lib
+includedir=@abs_top_srcdir@/include
Name: libguestfs
Version: @VERSION@
--
2.26.2
4 years, 3 months
[PATCH] daemon: inspect_fs_windows: Handle parted errors
by Sam Eiderman
By creating an empty disk and using it as the first disk of the vm (i.e.
/dev/sda, /dev/sdb{1,2} contains the windows fses) we change the
iteration order of the disks.
This causes inspect_os() to fail since Parted returns a Unix_error if
the device does not contain any partitions - fix this by handling this
Unix_error.
Signed-off-by: Sam Eiderman <sameid(a)google.com>
---
daemon/inspect_fs_windows.ml | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
index c4a05bc38..bc6b98b60 100644
--- a/daemon/inspect_fs_windows.ml
+++ b/daemon/inspect_fs_windows.ml
@@ -365,8 +365,10 @@ and map_registry_disk_blob_mbr devices blob =
let device =
List.find (
fun dev ->
- Parted.part_get_parttype dev = "msdos" &&
- pread dev 4 0x01b8 = diskid
+ try
+ Parted.part_get_parttype dev = "msdos" &&
+ pread dev 4 0x01b8 = diskid
+ with Unix.Unix_error (Unix.EINVAL, _, _) -> false
) devices in
(* Next 8 bytes are the offset of the partition in bytes(!) given as
@@ -402,7 +404,10 @@ and map_registry_disk_blob_gpt partitions blob =
fun part ->
let partnum = Devsparts.part_to_partnum part in
let device = Devsparts.part_to_dev part in
- let typ = Parted.part_get_parttype device in
+ let typ =
+ try
+ Parted.part_get_parttype device
+ with Unix.Unix_error (Unix.EINVAL, _, _) -> "unknown" in
if typ <> "gpt" then false
else (
let guid = Parted.part_get_gpt_guid device partnum in
--
2.27.0.212.ge8ba1cc988-goog
4 years, 3 months
[nbdkit PATCH v3 00/14] exportname filter
by Eric Blake
It's been several weeks since I posted v2 (I got distracted by
improving libnbd to better test things, which in turn surfaced some
major memory leak problems in nbdsh that are now fixed). Many of the
patches are minor rebases from v2, with the biggest changes being
fallout from:
- patch 2: rename nbdkit_add_default_export to nbdkit_use_default_export
- overall: this missed 1.22, so update appropriate documentation
- libnbd's 'nbdinfo --list' differs in behavior between 1.4.0 and 1.4.1
regarding descriptions, so fix the tests to work for both versions
- rebased on top of rewriting test-layers to use libnbd
- rebased on top of putting nbdkit_*_intern() in place already
I'm probably at the point where it is just worth committing this
series, and dealing with any further changes as followup patches.
Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively
001/14:[0059] [FC] 'api: Add .default_export'
002/14:[down] 'api: Add nbdkit_use_default_export'
003/14:[0059] [FC] 'server: Respond to NBD_INFO_NAME request'
004/14:[0021] [FC] 'sh, eval: Implement .default_export'
005/14:[0036] [FC] 'api: Alter .list_exports'
006/14:[0032] [FC] 'api: Add .export_description'
007/14:[0015] [FC] 'exportname: New filter'
008/14:[0049] [FC] 'filters: Add .export_description wrappers'
009/14:[0002] [FC] 'ext2: Supply .list_exports and .default_export'
010/14:[----] [--] 'nbd: Implement .default_export, .export_description'
011/14:[0010] [FC] 'nbd: Add dynamic-export=true option'
012/14:[0002] [FC] 'nbd: Implement .list_exports'
013/14:[0019] [FC] 'python: Implement .list_exports and friends'
014/14:[0017] [FC] 'ocaml: Implement .list_exports and friends'
Eric Blake (14):
api: Add .default_export
api: Add nbdkit_use_default_export
server: Respond to NBD_INFO_NAME request
sh, eval: Implement .default_export
api: Alter .list_exports
api: Add .export_description
exportname: New filter
filters: Add .export_description wrappers
ext2: Supply .list_exports and .default_export
nbd: Implement .default_export, .export_description
nbd: Add dynamic-export=true option
nbd: Implement .list_exports
python: Implement .list_exports and friends
ocaml: Implement .list_exports and friends
docs/nbdkit-filter.pod | 65 +++-
docs/nbdkit-plugin.pod | 112 +++++-
docs/nbdkit-protocol.pod | 14 +
.../exportname/nbdkit-exportname-filter.pod | 154 ++++++++
filters/ext2/nbdkit-ext2-filter.pod | 6 +
filters/log/nbdkit-log-filter.pod | 2 +-
plugins/eval/nbdkit-eval-plugin.pod | 6 +
plugins/file/nbdkit-file-plugin.pod | 9 +-
plugins/nbd/nbdkit-nbd-plugin.pod | 30 +-
plugins/python/nbdkit-python-plugin.pod | 25 ++
plugins/sh/nbdkit-sh-plugin.pod | 39 +-
include/nbdkit-common.h | 2 +
include/nbdkit-filter.h | 13 +-
include/nbdkit-plugin.h | 4 +-
configure.ac | 2 +
filters/exportname/Makefile.am | 67 ++++
tests/Makefile.am | 31 +-
server/internal.h | 15 +-
server/backend.c | 93 +++--
server/exports.c | 32 +-
server/filters.c | 31 +-
server/nbdkit.syms | 1 +
server/plugins.c | 33 +-
server/protocol-handshake-newstyle.c | 88 ++++-
server/test-public.c | 9 +-
plugins/ocaml/NBDKit.mli | 9 +
plugins/sh/methods.h | 2 +
plugins/ocaml/NBDKit.ml | 17 +
plugins/ocaml/example.ml | 33 +-
plugins/cc/cc.c | 73 ++--
plugins/eval/eval.c | 70 ++--
plugins/nbd/nbd.c | 250 +++++++++++--
plugins/ocaml/ocaml.c | 92 ++++-
plugins/ondemand/ondemand.c | 11 +-
plugins/python/python.c | 185 ++++++++--
plugins/sh/methods.c | 84 ++++-
plugins/sh/sh.c | 70 ++--
plugins/sh/example.sh | 2 +-
filters/exportname/exportname.c | 342 ++++++++++++++++++
filters/ext2/ext2.c | 122 +++++--
filters/gzip/gzip.c | 37 +-
filters/log/log.c | 8 +-
filters/partition/partition.c | 56 ++-
filters/tar/tar.c | 46 ++-
filters/tls-fallback/tls-fallback.c | 60 ++-
filters/xz/xz.c | 40 +-
tests/test-eval-exports.sh | 41 ++-
tests/test-export-info.sh | 111 ++++++
tests/test-exportname.sh | 193 ++++++++++
tests/test-ext2-exportname.sh | 73 ++++
tests/test-nbd-dynamic-content.sh | 75 ++++
tests/test-nbd-dynamic-list.sh | 162 +++++++++
tests/test-python-export-list.sh | 71 ++++
tests/test-tls-fallback.sh | 53 ++-
tests/python-export-list.py | 59 +++
tests/test-layers-filter.c | 13 +-
tests/test-layers-plugin.c | 8 +
tests/test-layers.c | 12 +
TODO | 20 +-
59 files changed, 2950 insertions(+), 433 deletions(-)
create mode 100644 filters/exportname/nbdkit-exportname-filter.pod
create mode 100644 filters/exportname/Makefile.am
create mode 100644 filters/exportname/exportname.c
create mode 100755 tests/test-export-info.sh
create mode 100755 tests/test-exportname.sh
create mode 100755 tests/test-ext2-exportname.sh
create mode 100755 tests/test-nbd-dynamic-content.sh
create mode 100755 tests/test-nbd-dynamic-list.sh
create mode 100755 tests/test-python-export-list.sh
create mode 100644 tests/python-export-list.py
--
2.28.0
4 years, 3 months
[PATCH v5 0/8] Configurable policy for handling deprecated interfaces
by Markus Armbruster
New option -compat lets you configure what to do when deprecated
interfaces get used. This is intended for testing users of the
management interfaces. It is experimental.
-compat deprecated-input=<in-policy> configures what to do when
deprecated input is received. Available policies:
* accept: Accept deprecated commands and arguments (default)
* reject: Reject them
* crash: Crash
-compat deprecated-output=<out-policy> configures what to do when
deprecated output is sent. Available output policies:
* accept: Emit deprecated command results and events (default)
* hide: Suppress them
For now, -compat covers only deprecated syntactic aspects of QMP. We
may want to extend it to cover semantic aspects, CLI, and experimental
features.
v5:
* Old PATCH 01-26 merged in commit f57587c7d47.
* Rebased, non-trivial conflicts in PATCH 1 due to Meson, and in PATCH
7 due to visitor changes
* PATCH 1: Comments updated for 5.2 [Eric]
* PATCH 2: Harmless missing initialization fixed [Eric]
* PATCH 3+4: Harmless missing has_FOO = true fixed [Eric]
* PATCH 6+7: Commit message tweaked
v4:
* PATCH 05+07: Temporary memory leak plugged [Marc-André]
* PATCH 23: Rewritten [Marc-André]
* PATCH 24: Comment typo [Marc-André]
* PATCH 30: Memory leaks plugged
v3:
* Rebased, non-trivial conflicts in PATCH 01+26+27+34 due to RST
conversion and code motion
* PATCH 28-29: Old PATCH 28 split up to ease review
* PATCH 30-31: New
* PATCH 32-33: Old PATCH 29 split up to ease review
Comparison to RFC (24 Oct 2019):
* Cover arguments and results in addition to commands and events
* Half-baked "[RFC PATCH 18/19] qapi: Include a warning in the
response to a deprecated command" dropped
See also last item of
Subject: Minutes of KVM Forum BoF on deprecating stuff
Date: Fri, 26 Oct 2018 16:03:51 +0200
Message-ID: <87mur0ls8o.fsf(a)dusky.pond.sub.org>
https://lists.nongnu.org/archive/html/qemu-devel/2018-10/msg05828.html
Cc: Lukáš Doktor <ldoktor(a)redhat.com>
Cc: libguestfs(a)redhat.com
Cc: libvir-list(a)redhat.com
Cc: Daniel P. Berrange <berrange(a)redhat.com>
Cc: Peter Krempa <pkrempa(a)redhat.com>
Cc: Kevin Wolf <kwolf(a)redhat.com>
Markus Armbruster (8):
qemu-options: New -compat to set policy for deprecated interfaces
qapi: Implement deprecated-output=hide for QMP command results
qapi: Implement deprecated-output=hide for QMP events
qapi: Implement deprecated-output=hide for QMP event data
qapi: Implement deprecated-output=hide for QMP introspection
qapi: Implement deprecated-input=reject for QMP commands
qapi: Implement deprecated-input=reject for QMP command arguments
qapi: New -compat deprecated-input=crash
qapi/compat.json | 52 ++++++++++++
qapi/introspect.json | 2 +-
qapi/qapi-schema.json | 1 +
include/qapi/compat-policy.h | 20 +++++
include/qapi/qmp/dispatch.h | 1 +
include/qapi/qobject-input-visitor.h | 9 +++
include/qapi/qobject-output-visitor.h | 9 +++
include/qapi/visitor-impl.h | 6 ++
include/qapi/visitor.h | 18 +++++
monitor/monitor-internal.h | 3 -
monitor/misc.c | 2 -
monitor/qmp-cmds-control.c | 100 +++++++++++++++++++++---
qapi/qapi-visit-core.c | 18 +++++
qapi/qmp-dispatch.c | 17 ++++
qapi/qobject-input-visitor.c | 29 +++++++
qapi/qobject-output-visitor.c | 19 +++++
softmmu/vl.c | 17 ++++
storage-daemon/qemu-storage-daemon.c | 2 -
tests/test-qmp-cmds.c | 91 +++++++++++++++++++--
tests/test-qmp-event.c | 41 ++++++++++
qapi/meson.build | 1 +
qapi/trace-events | 2 +
qemu-options.hx | 22 ++++++
scripts/qapi/commands.py | 14 ++--
scripts/qapi/events.py | 22 +++++-
scripts/qapi/visit.py | 15 ++++
tests/qapi-schema/qapi-schema-test.json | 20 +++--
tests/qapi-schema/qapi-schema-test.out | 20 ++---
28 files changed, 522 insertions(+), 51 deletions(-)
create mode 100644 qapi/compat.json
create mode 100644 include/qapi/compat-policy.h
--
2.26.2
4 years, 3 months
[libnbd PATCH] nbdsh: Hide nbd.Error from abrt-python3-handler
by Eric Blake
When using nbdsh for scripting, it is convenient to let nbdsh fail
with status 1 when encountering an API failure. However, doing so by
letting the nbd.Error exception leak all the way causes ABRT (on
Fedora 32 at least) to assume the program crashed from a programming
error, and needlessly complicates clients to have to add try: blocks.
Better is if nbdsh itself prints the same stack trace that python
would, but handles the error and exits python cleanly so that ABRT
does not think that the exception was unhandled.
See https://github.com/libguestfs/nbdkit/commit/e13048fd9 for an
example of client cleanup made more verbose if we don't patch libnbd.
---
Is it worth a command-line option, off by default, but that the user
can opt in to, where the option being set says we re-raise the excpetion
instead of handling it ourselves?
python/nbdsh.py | 18 ++++++++++++------
sh/Makefile.am | 4 +++-
sh/test-error.sh | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 7 deletions(-)
create mode 100755 sh/test-error.sh
diff --git a/python/nbdsh.py b/python/nbdsh.py
index c9a7beb..93d4998 100644
--- a/python/nbdsh.py
+++ b/python/nbdsh.py
@@ -1,5 +1,5 @@
# NBD client library in userspace
-# Copyright (C) 2013-2019 Red Hat Inc.
+# Copyright (C) 2013-2020 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -16,6 +16,9 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+import traceback
+
+
# The NBD shell.
def shell():
import argparse
@@ -95,8 +97,12 @@ help(nbd) # Display documentation
else:
# https://stackoverflow.com/a/11754346
d = dict(locals(), **globals())
- for c in args.command:
- if c != '-':
- exec(c, d, d)
- else:
- exec(sys.stdin.read(), d, d)
+ try:
+ for c in args.command:
+ if c != '-':
+ exec(c, d, d)
+ else:
+ exec(sys.stdin.read(), d, d)
+ except nbd.Error:
+ traceback.print_exc()
+ sys.exit(1)
diff --git a/sh/Makefile.am b/sh/Makefile.am
index 415e241..8c4b982 100644
--- a/sh/Makefile.am
+++ b/sh/Makefile.am
@@ -1,5 +1,5 @@
# nbd client library in userspace
-# Copyright (C) 2013-2019 Red Hat Inc.
+# Copyright (C) 2013-2020 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@ EXTRA_DIST = \
examples/LICENSE-FOR-EXAMPLES \
examples/hexdump.sh \
test-context.sh \
+ test-error.sh \
test-help.sh \
test-pattern.sh \
test-version.sh \
@@ -49,6 +50,7 @@ LOG_COMPILER = $(top_builddir)/run
TESTS = \
test-help.sh \
test-version.sh \
+ test-error.sh \
$(NULL)
if HAVE_NBDKIT
diff --git a/sh/test-error.sh b/sh/test-error.sh
new file mode 100755
index 0000000..d8a1d84
--- /dev/null
+++ b/sh/test-error.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+# nbd client library in userspace
+# Copyright (C) 2019-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Test how nbdsh -c handles errors
+fail=0
+
+. ../tests/functions.sh
+
+files='test-error.out test-error.err'
+cleanup_fn rm -f $files
+rm -f $files
+
+# Triggering nbd.Error non-interactively prints the error
+nbdsh -c 'h.is_read_only()' > test-error.out 2> test-error.err && fail=1
+test ! -s test-error.out
+cat test-error.err
+grep Traceback test-error.err
+grep 'in is_read_only' test-error.err
+grep '^nbd\.Error: nbd_is_read_only: ' test-error.err
+
+exit $fail
--
2.28.0
4 years, 3 months