1nbdkit-python-plugin(3) NBDKIT nbdkit-python-plugin(3)
2
3
4
6 nbdkit-python-plugin - nbdkit python plugin
7
9 nbdkit python /path/to/plugin.py [arguments...]
10
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
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
60 • python3 on $PATH
61
62 • python 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
467 $plugindir/nbdkit-python-plugin.so
468 The plugin.
469
470 Use "nbdkit --dump-config" to find the location of $plugindir.
471
473 "nbdkit-python-plugin" first appeared in nbdkit 1.2.
474
476 nbdkit(1), nbdkit-plugin(3), python(1).
477
479 Eric Blake
480
481 Richard W.M. Jones
482
483 Nir Soffer
484
486 Copyright Red Hat
487
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)