On Wed, Jan 25, 2017 at 08:42:35PM -0600, Eric Blake wrote:
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.
This one looks OK. I didn't apply it because it requires the previous patch. Rich.
Signed-off-by: Eric Blake <eblake@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
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org