[Libguestfs] [nbdkit PATCH v3 3/4] python: Expose nbdkit_set_error to python script

Eric Blake eblake at redhat.com
Fri Jan 27 02:58:36 UTC 2017


In addition to calling python functions from C, we want to make
script writing easier by exposing C functions to python.  For
now, just wrap nbdkit_set_error(), as that will be needed for
an optimal implementation of a zero() callback.

Signed-off-by: Eric Blake <eblake at redhat.com>

---
v2: tweak docs
---
 plugins/python/nbdkit-python-plugin.pod | 30 +++++++++++++++++++++++++-----
 plugins/python/python.c                 | 18 ++++++++++++++++++
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
index 63e5f96..a1e3d2b 100644
--- a/plugins/python/nbdkit-python-plugin.pod
+++ b/plugins/python/nbdkit-python-plugin.pod
@@ -63,9 +63,22 @@ does not need to be executable.  In fact it's a good idea not to do
 that, because running the plugin directly as a Python script won't
 work.

+=head2 METHODS
+
+Your script may use C<import nbdkit> to have access to the following
+methods in the C<nbdkit> module:
+
+ nbdkit.set_error(I<err>)
+
+Record C<err> as the reason you are about to throw an exception. C<err>
+should correspond to usual errno values, where it may help to
+C<import errno>.
+
 =head2 EXCEPTIONS

-Python callbacks should throw exceptions to indicate errors.
+Python callbacks should throw exceptions to indicate errors.  Remember
+to use C<nbdkit.set_error> if you need to control which error is sent
+back to the client; if omitted, the client will see an error of C<EIO>.

 =head2 PYTHON CALLBACKS

@@ -158,7 +171,8 @@ disk starting at C<offset>.

 NBD only supports whole reads, so your function should try to read
 the whole region (perhaps requiring a loop).  If the read fails or
-is partial, your function should throw an exception.
+is partial, your function should throw an exception, optionally using
+C<nbdkit.set_error> first.

 =item C<pwrite>

@@ -174,7 +188,8 @@ C<offset>.

 NBD only supports whole writes, so your function should try to
 write the whole region (perhaps requiring a loop).  If the write
-fails or is partial, your function should throw an exception.
+fails or is partial, your function should throw an exception,
+ optionally using C<nbdkit.set_error> first.

 =item C<flush>

@@ -186,6 +201,9 @@ fails or is partial, your function should throw an exception.
 The body of your C<flush> function should do a L<sync(2)> or
 L<fdatasync(2)> or equivalent on the backing store.

+If the flush fails, your function should throw an exception, optionally
+using C<nbdkit.set_error> first.
+
 =item C<trim>

 (Optional)
@@ -194,7 +212,8 @@ L<fdatasync(2)> or equivalent on the backing store.
    # no return value

 The body of your C<trim> function should "punch a hole" in the
-backing store.
+backing store.  If the trim fails, your function should throw an
+exception, optionally using C<nbdkit.set_error> first.

 =back

@@ -210,7 +229,8 @@ constructs.
 =item Missing: C<errno_is_reliable>

 This is not needed because the process of gluing Python code into C cannot
-reliably use C<errno>.
+reliably use C<errno>.  Instead, call C<nbdkit.set_error> when reporting
+a failure.

 =item Missing: C<name>, C<version>, C<longname>, C<description>, C<config_help>

diff --git a/plugins/python/python.c b/plugins/python/python.c
index 7e9fc1e..631411e 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -54,6 +54,23 @@
 static const char *script;
 static PyObject *module;

+static PyObject *
+set_error (PyObject *self, PyObject *args)
+{
+  int err;
+
+  if (!PyArg_ParseTuple(args, "i", &err))
+    return NULL;
+  nbdkit_set_error (err);
+  Py_RETURN_NONE;
+}
+
+static PyMethodDef NbdkitMethods[] = {
+  { "set_error", set_error, METH_VARARGS,
+    "Store an errno value prior to throwing an exception" },
+  { NULL }
+};
+
 /* Is a callback defined? */
 static int
 callback_defined (const char *name, PyObject **obj_rtn)
@@ -91,6 +108,7 @@ static void
 py_load (void)
 {
   Py_Initialize ();
+  Py_InitModule("nbdkit", NbdkitMethods);
 }

 static void
-- 
2.9.3




More information about the Libguestfs mailing list