1nbdkit-python-plugin(3)             NBDKIT             nbdkit-python-plugin(3)
2
3
4

NAME

6       nbdkit-python-plugin - nbdkit python plugin
7

SYNOPSIS

9        nbdkit python /path/to/plugin.py [arguments...]
10

DESCRIPTION

12       "nbdkit-python-plugin" is an embedded Python interpreter for nbdkit(1),
13       allowing you to write nbdkit plugins in Python 3.
14
15   If you have been given an nbdkit Python plugin
16       Assuming you have a Python script which is an nbdkit plugin, you run it
17       like this:
18
19        nbdkit python /path/to/plugin.py
20
21       You may have to add further "key=value" arguments to the command line.
22       Read the Python script to see if it requires any.
23

WRITING A PYTHON NBDKIT PLUGIN

25       For example plugins written in Python, see:
26       https://gitlab.com/nbdkit/nbdkit/blob/master/plugins/python/examples
27
28       Broadly speaking, Python nbdkit plugins work like C ones, so you should
29       read nbdkit-plugin(3) first.
30
31       To write a Python nbdkit plugin, you create a Python file which
32       contains at least the following required functions (in the top level
33       "__main__" module):
34
35        API_VERSION = 2
36        def open(readonly):
37          # see below
38        def get_size(h):
39          # see below
40        def pread(h, buf, offset, flags):
41          # see below
42
43       Note that the subroutines must have those literal names (like "open"),
44       because the C part looks up and calls those functions directly.  You
45       may want to include documentation and globals (eg. for storing global
46       state).  Any other top level statements are run when the script is
47       loaded, just like ordinary Python.
48
49   Python versions
50       Since nbdkit ≥ 1.16 only Python 3 is supported.  If you wish to
51       continue using nbdkit plugins written in Python 2 then you must use
52       nbdkit ≤ 1.14, but we advise you to update your plugins.
53
54       The version of Python 3 is chosen when nbdkit is built.  This is
55       compiled in and can't be changed at runtime.  "./configure" looks for
56       (in order):
57
58       •   the "PYTHON" variable (eg "./configure PYTHON=/usr/bin/python3.9")
59
60python3 on $PATH
61
62python on $PATH
63
64       "./configure" will fail if the first interpreter found is a Python 2
65       interpreter.
66
67       To find out which version of Python "nbdkit-python-plugin" was compiled
68       for, use the --dump-plugin option:
69
70        $ nbdkit python --dump-plugin
71        ...
72        python_version=3.7.0
73        python_pep_384_abi_version=3
74
75   API versions
76       The nbdkit API has evolved and new versions are released periodically.
77       To ensure backwards compatibility plugins have to opt in to the new
78       version.  From Python you do this by declaring a constant in your
79       module:
80
81        API_VERSION = 2
82
83       (where 2 is the latest version at the time this documentation was
84       written).  All newly written Python modules must have this constant.
85
86   Executable script
87       If you want you can make the script executable and include a "shebang"
88       at the top:
89
90        #!/usr/sbin/nbdkit python
91
92       See also "Shebang scripts" in nbdkit(1).
93
94       These scripts can also be installed in the $plugindir.  See "WRITING
95       PLUGINS IN OTHER PROGRAMMING LANGUAGES" in nbdkit-plugin(3).
96
97   Module functions
98       Your script may use "import nbdkit" to have access to the following
99       methods in the "nbdkit" module:
100
101       "nbdkit.debug(msg)"
102
103       Send a debug message to stderr or syslog if verbose messages are
104       enabled.
105
106       "nbdkit.disconnect(force)"
107
108       Disconnect from the client.  If "force" is "True" then nbdkit will
109       disconnect the client immediately.
110
111       "nbdkit.export_name()"
112
113       Return the export name negotiated with the client as a Unicode string.
114       Note this should not be trusted because the client can send whatever it
115       wants.
116
117       "nbdkit.parse_size(str)"
118
119       Parse a string (such as "100M") into a size in bytes. Wraps the
120       nbdkit_parse_size() C function.
121
122       "nbdkit.parse_probability(what, str)"
123
124       Parse a string (such as "100%") into a probability, returning a
125       floating point number. Wraps the nbdkit_parse_probability() C function.
126
127       "nbdkit.set_error(err)"
128
129       Record "err" as the reason you are about to throw an exception. "err"
130       should correspond to usual errno values, where it may help to "import
131       errno".
132
133       "nbdkit.shutdown()"
134
135       Request asynchronous server shutdown.
136
137   Module constants
138       After "import nbdkit" the following constants are available.  These are
139       used in the callbacks below.
140
141       "nbdkit.THREAD_MODEL_SERIALIZE_CONNECTIONS"
142       "nbdkit.THREAD_MODEL_SERIALIZE_ALL_REQUESTS"
143       "nbdkit.THREAD_MODEL_SERIALIZE_REQUESTS"
144       "nbdkit.THREAD_MODEL_PARALLEL"
145           Possible return values from thread_model().
146
147       "nbdkit.FLAG_MAY_TRIM"
148       "nbdkit.FLAG_FUA"
149       "nbdkit.FLAG_REQ_ONE"
150       "nbdkit.FLAG_FAST_ZERO"
151           Flags bitmap passed to certain plugin callbacks.  Not all callbacks
152           with a flags parameter use all of these flags, consult the
153           documentation below and nbdkit-plugin(3).
154
155       "nbdkit.FUA_NONE"
156       "nbdkit.FUA_EMULATE"
157       "nbdkit.FUA_NATIVE"
158           Possible return values from can_fua().
159
160       "nbdkit.CACHE_NONE"
161       "nbdkit.CACHE_EMULATE"
162       "nbdkit.CACHE_NATIVE"
163           Possible return values from can_cache().
164
165       "nbdkit.EXTENT_HOLE"
166       "nbdkit.EXTENT_ZERO"
167           Used in the "type" field returned by extents().
168
169   Threads
170       The thread model for Python callbacks defaults to
171       "nbdkit.THREAD_MODEL_SERIALIZE_ALL_REQUESTS".
172
173       Since nbdkit 1.22 it has been possible to set this by implementing a
174       thread_model() function which returns one of the constants
175       "nbdkit.THREAD_MODEL_*".
176
177       The Python Global Interpreter Lock (GIL) is still used, so Python code
178       does not run in parallel.  However if a plugin callback calls a library
179       which blocks (eg. to make an HTTP request), then another callback might
180       be executed in parallel.  Plugins which use
181       "nbdkit.THREAD_MODEL_SERIALIZE_REQUESTS" or
182       "nbdkit.THREAD_MODEL_PARALLEL" may need to use locks on shared data.
183
184   Exceptions
185       Python callbacks should throw exceptions to indicate errors.  Remember
186       to use "nbdkit.set_error" if you need to control which error is sent
187       back to the client; if omitted, the client will see an error of "EIO".
188
189   Python callbacks
190       This just documents the arguments to the callbacks in Python, and any
191       way that they differ from the C callbacks.  In all other respects they
192       work the same way as the C callbacks, so you should go and read
193       nbdkit-plugin(3).
194
195       "dump_plugin"
196           (Optional)
197
198           There are no arguments or return value.
199
200       "config"
201           (Optional)
202
203            def config(key, value):
204              # no return value
205
206       "config_complete"
207           (Optional)
208
209           There are no arguments or return value.
210
211       "thread_model"
212           (Optional, nbdkit ≥ 1.22)
213
214            def thread_model():
215              return nbdkit.THEAD_MODEL_SERIALIZE_ALL_REQUESTS
216
217           See "Threads" above.
218
219       "get_ready"
220           (Optional)
221
222           There are no arguments or return value.
223
224       "after_fork"
225           (Optional, nbdkit ≥ 1.26)
226
227           There are no arguments or return value.
228
229       "cleanup"
230           (Optional, nbdkit ≥ 1.28)
231
232           There are no arguments or return value.
233
234       "list_exports"
235           (Optional)
236
237            def list_exports(readonly, is_tls):
238              # return an iterable object (eg. list) of
239              # (name, description) tuples or bare names:
240              return [ (name1, desc1), name2, (name3, desc3), ... ]
241
242       "default_export"
243           (Optional)
244
245            def default_export(readonly, is_tls):
246              # return a string
247              return "name"
248
249       "preconnect"
250           (Optional, nbdkit ≥ 1.26)
251
252            def preconnect(readonly):
253              # no return value
254
255       "open"
256           (Required)
257
258            def open(readonly):
259              # return handle
260
261           You can return any Python value (even "None") as the handle.  It is
262           passed back as the first arg 'h' in subsequent calls.  To return an
263           error from this method you must throw an exception.
264
265       "close"
266           (Optional)
267
268            def close(h):
269              # no return value
270
271           After "close" returns, the reference count of the handle is
272           decremented in the C part, which usually means that the handle and
273           its contents will be garbage collected.
274
275       "export_description"
276           (Optional)
277
278            def export_description(h):
279              # return a string
280              return "description"
281
282       "get_size"
283           (Required)
284
285            def get_size(h):
286              # return the size of the disk
287
288       "block_size"
289           (Option)
290
291            def block_size(h):
292              # return triple (minimum, preferred, maximum) block size
293
294       "is_rotational"
295           (Optional)
296
297            def is_rotational(h):
298              # return a boolean
299
300       "can_multi_conn"
301           (Optional)
302
303            def can_multi_conn(h):
304              # return a boolean
305
306       "can_write"
307           (Optional)
308
309            def can_write(h):
310              # return a boolean
311
312       "can_flush"
313           (Optional)
314
315            def can_flush(h):
316              # return a boolean
317
318       "can_trim"
319           (Optional)
320
321            def can_trim(h):
322              # return a boolean
323
324       "can_zero"
325           (Optional)
326
327            def can_zero(h):
328              # return a boolean
329
330       "can_fast_zero"
331           (Optional)
332
333            def can_fast_zero(h):
334              # return a boolean
335
336       "can_fua"
337           (Optional)
338
339            def can_fua(h):
340              # return nbdkit.FUA_NONE or nbdkit.FUA_EMULATE
341              # or nbdkit.FUA_NATIVE
342
343       "can_cache"
344           (Optional)
345
346            def can_cache(h):
347              # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE
348              # or nbdkit.CACHE_NATIVE
349
350       "can_extents"
351           (Optional)
352
353            def can_extents(h):
354              # return a boolean
355
356       "pread"
357           (Required)
358
359            def pread(h, buf, offset, flags):
360              # read into the buffer
361
362           The body of your "pread" function should read exactly len(buf)
363           bytes of data starting at disk "offset" and write it into the
364           buffer "buf".  "flags" is always 0.
365
366           NBD only supports whole reads, so your function should try to read
367           the whole region (perhaps requiring a loop).  If the read fails or
368           is partial, your function should throw an exception, optionally
369           using "nbdkit.set_error" first.
370
371       "pwrite"
372           (Optional)
373
374            def pwrite(h, buf, offset, flags):
375              length = len(buf)
376              # no return value
377
378           The body of your "pwrite" function should write the buffer "buf" to
379           the disk.  You should write "count" bytes to the disk starting at
380           "offset".  "flags" may contain "nbdkit.FLAG_FUA".
381
382           NBD only supports whole writes, so your function should try to
383           write the whole region (perhaps requiring a loop).  If the write
384           fails or is partial, your function should throw an exception,
385            optionally using "nbdkit.set_error" first.
386
387       "flush"
388           (Optional)
389
390            def flush(h, flags):
391              # no return value
392
393           The body of your "flush" function should do a sync(2) or
394           fdatasync(2) or equivalent on the backing store.  "flags" is always
395           0.
396
397           If the flush fails, your function should throw an exception,
398           optionally using "nbdkit.set_error" first.
399
400       "trim"
401           (Optional)
402
403            def trim(h, count, offset, flags):
404              # no return value
405
406           The body of your "trim" function should "punch a hole" in the
407           backing store.  "flags" may contain "nbdkit.FLAG_FUA".  If the trim
408           fails, your function should throw an exception, optionally using
409           "nbdkit.set_error" first.
410
411       "zero"
412           (Optional)
413
414            def zero(h, count, offset, flags):
415              # no return value
416
417           The body of your "zero" function should ensure that "count" bytes
418           of the disk, starting at "offset", will read back as zero.  "flags"
419           is a bitmask which may include "nbdkit.FLAG_MAY_TRIM",
420           "nbdkit.FLAG_FUA", "nbdkit.FLAG_FAST_ZERO".
421
422           NBD only supports whole writes, so your function should try to
423           write the whole region (perhaps requiring a loop).
424
425           If the write fails or is partial, your function should throw an
426           exception, optionally using "nbdkit.set_error" first.  In
427           particular, if you would like to automatically fall back to
428           "pwrite" (perhaps because there is nothing to optimize if
429           "flags & nbdkit.FLAG_MAY_TRIM" is false), use
430           "nbdkit.set_error(errno.EOPNOTSUPP)".
431
432       "cache"
433           (Optional)
434
435            def cache(h, count, offset, flags):
436              # no return value
437
438           The body of your "cache" function should prefetch data in the
439           indicated range.
440
441           If the cache operation fails, your function should throw an
442           exception, optionally using "nbdkit.set_error" first.
443
444       "extents"
445           (Optional)
446
447            def extents(h, count, offset, flags):
448              # return an iterable object (eg. list) of
449              # (offset, length, type) tuples:
450              return [ (off1, len1, type1), (off2, len2, type2), ... ]
451
452   Missing callbacks
453       Missing: "load"
454           This is not needed since you can use regular Python mechanisms like
455           top level statements to run code when the module is loaded.
456
457       Missing: "unload"
458           This is missing, but in nbdkit ≥ 1.28 you can put code in the
459           cleanup() function to have it run when nbdkit exits.  In earlier
460           versions of nbdkit, using a Python atexit handler is recommended.
461
462       Missing: "name", "version", "longname", "description", "config_help",
463       "magic_config_key".
464           These are not yet supported.
465

FILES

467       $plugindir/nbdkit-python-plugin.so
468           The plugin.
469
470           Use "nbdkit --dump-config" to find the location of $plugindir.
471

VERSION

473       "nbdkit-python-plugin" first appeared in nbdkit 1.2.
474

SEE ALSO

476       nbdkit(1), nbdkit-plugin(3), python(1).
477

AUTHORS

479       Eric Blake
480
481       Richard W.M. Jones
482
483       Nir Soffer
484
486       Copyright Red Hat
487

LICENSE

489       Redistribution and use in source and binary forms, with or without
490       modification, are permitted provided that the following conditions are
491       met:
492
493       •   Redistributions of source code must retain the above copyright
494           notice, this list of conditions and the following disclaimer.
495
496       •   Redistributions in binary form must reproduce the above copyright
497           notice, this list of conditions and the following disclaimer in the
498           documentation and/or other materials provided with the
499           distribution.
500
501       •   Neither the name of Red Hat nor the names of its contributors may
502           be used to endorse or promote products derived from this software
503           without specific prior written permission.
504
505       THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
506       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
507       IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
508       PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
509       LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
510       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
511       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
512       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
513       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
514       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
515       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
516
517
518
519nbdkit-1.36.2                     2023-11-26           nbdkit-python-plugin(3)
Impressum