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 <ebl...@redhat.com> --- plugins/python/nbdkit-python-plugin.pod | 27 +++++++++++++++++++++++---- plugins/python/python.c | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod index 9b0f0ef..8b3d08c 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. =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 diff --git a/plugins/python/python.c b/plugins/python/python.c index 0504715..4a0ff50 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 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs