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.
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 In nbdkit ≤ 1.14, either Python 2 or 3 could be used. It was selected
51 at compile time by either:
52
53 ./configure
54
55 which selected the version of Python by looking at the "python"
56 interpreter found on the $PATH. Or:
57
58 ./configure PYTHON=/usr/bin/python3
59
60 which allowed you to select a different interpreter and hence a
61 different version of Python.
62
63 nbdkit ≥ 1.16 drops all support for Python 2, since Python 2 has
64 reached its end of life.
65
66 The new behaviour is that "./configure" looks for "python3" or "python"
67 (in that order) on the $PATH. It will fail if the first interpreter it
68 finds is a Python 2 interpreter. You may also still choose a Python
69 interpreter by setting the "PYTHON" variable at configure time as
70 above.
71
72 If you wish to continue using nbdkit plugins written in Python 2 then
73 you must use nbdkit ≤ 1.14, but we would advise you to update your
74 plugins.
75
76 To find out which version the Python plugin was compiled for, use the
77 --dump-plugin option, eg:
78
79 $ nbdkit python --dump-plugin
80 ...
81 python_version=3.7.0
82 python_pep_384_abi_version=3
83
84 API versions
85 The nbdkit API has evolved and new versions are released periodically.
86 To ensure backwards compatibility plugins have to opt in to the new
87 version. From Python you do this by declaring a constant in your
88 module:
89
90 API_VERSION = 2
91
92 (where 2 is the latest version at the time this documentation was
93 written). All newly written Python modules must have this constant.
94
95 Executable script
96 If you want you can make the script executable and include a "shebang"
97 at the top:
98
99 #!/usr/sbin/nbdkit python
100
101 See also "Shebang scripts" in nbdkit(1).
102
103 These scripts can also be installed in the $plugindir. See "WRITING
104 PLUGINS IN OTHER PROGRAMMING LANGUAGES" in nbdkit-plugin(3).
105
106 Module functions
107 Your script may use "import nbdkit" to have access to the following
108 methods in the "nbdkit" module:
109
110 "nbdkit.debug(msg)"
111
112 Send a debug message to stderr or syslog if verbose messages are
113 enabled.
114
115 "nbdkit.export_name()"
116
117 Return the export name negotiated with the client as a Unicode string.
118 Note this should not be trusted because the client can send whatever it
119 wants.
120
121 "nbdkit.set_error(err)"
122
123 Record "err" as the reason you are about to throw an exception. "err"
124 should correspond to usual errno values, where it may help to "import
125 errno".
126
127 "nbdkit.shutdown()"
128
129 Request asynchronous server shutdown.
130
131 Module constants
132 After "import nbdkit" the following constants are available. These are
133 used in the callbacks below.
134
135 "nbdkit.THREAD_MODEL_SERIALIZE_CONNECTIONS"
136 "nbdkit.THREAD_MODEL_SERIALIZE_ALL_REQUESTS"
137 "nbdkit.THREAD_MODEL_SERIALIZE_REQUESTS"
138 "nbdkit.THREAD_MODEL_PARALLEL"
139 Possible return values from "thread_model()".
140
141 "nbdkit.FLAG_MAY_TRIM"
142 "nbdkit.FLAG_FUA"
143 "nbdkit.FLAG_REQ_ONE"
144 "nbdkit.FLAG_FAST_ZERO"
145 Flags bitmap passed to certain plugin callbacks. Not all callbacks
146 with a flags parameter use all of these flags, consult the
147 documentation below and nbdkit-plugin(3).
148
149 "nbdkit.FUA_NONE"
150 "nbdkit.FUA_EMULATE"
151 "nbdkit.FUA_NATIVE"
152 Possible return values from "can_fua()".
153
154 "nbdkit.CACHE_NONE"
155 "nbdkit.CACHE_EMULATE"
156 "nbdkit.CACHE_NATIVE"
157 Possible return values from "can_cache()".
158
159 "nbdkit.EXTENT_HOLE"
160 "nbdkit.EXTENT_ZERO"
161 Used in the "type" field returned by "extents()".
162
163 Threads
164 The thread model for Python callbacks defaults to
165 "nbdkit.THREAD_MODEL_SERIALIZE_ALL_REQUESTS".
166
167 Since nbdkit 1.22 it has been possible to set this by implementing a
168 "thread_model()" function which returns one of the constants
169 "nbdkit.THREAD_MODEL_*".
170
171 The Python Global Interpreter Lock (GIL) is still used, so Python code
172 does not run in parallel. However if a plugin callback calls a library
173 which blocks (eg. to make an HTTP request), then another callback might
174 be executed in parallel. Plugins which use
175 "nbdkit.THREAD_MODEL_SERIALIZE_REQUESTS" or
176 "nbdkit.THREAD_MODEL_PARALLEL" may need to use locks on shared data.
177
178 Exceptions
179 Python callbacks should throw exceptions to indicate errors. Remember
180 to use "nbdkit.set_error" if you need to control which error is sent
181 back to the client; if omitted, the client will see an error of "EIO".
182
183 Python callbacks
184 This just documents the arguments to the callbacks in Python, and any
185 way that they differ from the C callbacks. In all other respects they
186 work the same way as the C callbacks, so you should go and read
187 nbdkit-plugin(3).
188
189 "dump_plugin"
190 (Optional)
191
192 There are no arguments or return value.
193
194 "config"
195 (Optional)
196
197 def config(key, value):
198 # no return value
199
200 "config_complete"
201 (Optional)
202
203 There are no arguments or return value.
204
205 "thread_model"
206 (Optional, nbdkit ≥ 1.22)
207
208 def thread_model():
209 return nbdkit.THEAD_MODEL_SERIALIZE_ALL_REQUESTS
210
211 See "Threads" above.
212
213 "get_ready"
214 (Optional)
215
216 There are no arguments or return value.
217
218 "after_fork"
219 (Optional, nbdkit ≥ 1.26)
220
221 There are no arguments or return value.
222
223 "list_exports"
224 (Optional)
225
226 def list_exports(readonly, is_tls):
227 # return an iterable object (eg. list) of
228 # (name, description) tuples or bare names:
229 return [ (name1, desc1), name2, (name3, desc3), ... ]
230
231 "default_export"
232 (Optional)
233
234 def default_export(readonly, is_tls):
235 # return a string
236 return "name"
237
238 "preconnect"
239 (Optional, nbdkit ≥ 1.26)
240
241 def preconnect(readonly):
242 # no return value
243
244 "open"
245 (Required)
246
247 def open(readonly):
248 # return handle
249
250 You can return any non-NULL Python value as the handle. It is
251 passed back in subsequent calls.
252
253 "close"
254 (Optional)
255
256 def close(h):
257 # no return value
258
259 After "close" returns, the reference count of the handle is
260 decremented in the C part, which usually means that the handle and
261 its contents will be garbage collected.
262
263 "export_description"
264 (Optional)
265
266 def export_description(h):
267 # return a string
268 return "description"
269
270 "get_size"
271 (Required)
272
273 def get_size(h):
274 # return the size of the disk
275
276 "is_rotational"
277 (Optional)
278
279 def is_rotational(h):
280 # return a boolean
281
282 "can_multi_conn"
283 (Optional)
284
285 def can_multi_conn(h):
286 # return a boolean
287
288 "can_write"
289 (Optional)
290
291 def can_write(h):
292 # return a boolean
293
294 "can_flush"
295 (Optional)
296
297 def can_flush(h):
298 # return a boolean
299
300 "can_trim"
301 (Optional)
302
303 def can_trim(h):
304 # return a boolean
305
306 "can_zero"
307 (Optional)
308
309 def can_zero(h):
310 # return a boolean
311
312 "can_fast_zero"
313 (Optional)
314
315 def can_fast_zero(h):
316 # return a boolean
317
318 "can_fua"
319 (Optional)
320
321 def can_fua(h):
322 # return nbdkit.FUA_NONE or nbdkit.FUA_EMULATE
323 # or nbdkit.FUA_NATIVE
324
325 "can_cache"
326 (Optional)
327
328 def can_cache(h):
329 # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE
330 # or nbdkit.CACHE_NATIVE
331
332 "can_extents"
333 (Optional)
334
335 def can_extents(h):
336 # return a boolean
337
338 "pread"
339 (Required)
340
341 def pread(h, buf, offset, flags):
342 # read into the buffer
343
344 The body of your "pread" function should read exactly "len(buf)"
345 bytes of data starting at disk "offset" and write it into the
346 buffer "buf". "flags" is always 0.
347
348 NBD only supports whole reads, so your function should try to read
349 the whole region (perhaps requiring a loop). If the read fails or
350 is partial, your function should throw an exception, optionally
351 using "nbdkit.set_error" first.
352
353 "pwrite"
354 (Optional)
355
356 def pwrite(h, buf, offset, flags):
357 length = len(buf)
358 # no return value
359
360 The body of your "pwrite" function should write the buffer "buf" to
361 the disk. You should write "count" bytes to the disk starting at
362 "offset". "flags" may contain "nbdkit.FLAG_FUA".
363
364 NBD only supports whole writes, so your function should try to
365 write the whole region (perhaps requiring a loop). If the write
366 fails or is partial, your function should throw an exception,
367 optionally using "nbdkit.set_error" first.
368
369 "flush"
370 (Optional)
371
372 def flush(h, flags):
373 # no return value
374
375 The body of your "flush" function should do a sync(2) or
376 fdatasync(2) or equivalent on the backing store. "flags" is always
377 0.
378
379 If the flush fails, your function should throw an exception,
380 optionally using "nbdkit.set_error" first.
381
382 "trim"
383 (Optional)
384
385 def trim(h, count, offset, flags):
386 # no return value
387
388 The body of your "trim" function should "punch a hole" in the
389 backing store. "flags" may contain "nbdkit.FLAG_FUA". If the trim
390 fails, your function should throw an exception, optionally using
391 "nbdkit.set_error" first.
392
393 "zero"
394 (Optional)
395
396 def zero(h, count, offset, flags):
397 # no return value
398
399 The body of your "zero" function should ensure that "count" bytes
400 of the disk, starting at "offset", will read back as zero. "flags"
401 is a bitmask which may include "nbdkit.FLAG_MAY_TRIM",
402 "nbdkit.FLAG_FUA", "nbdkit.FLAG_FAST_ZERO".
403
404 NBD only supports whole writes, so your function should try to
405 write the whole region (perhaps requiring a loop).
406
407 If the write fails or is partial, your function should throw an
408 exception, optionally using "nbdkit.set_error" first. In
409 particular, if you would like to automatically fall back to
410 "pwrite" (perhaps because there is nothing to optimize if
411 "flags & nbdkit.FLAG_MAY_TRIM" is false), use
412 "nbdkit.set_error(errno.EOPNOTSUPP)".
413
414 "cache"
415 (Optional)
416
417 def cache(h, count, offset, flags):
418 # no return value
419
420 The body of your "cache" function should prefetch data in the
421 indicated range.
422
423 If the cache operation fails, your function should throw an
424 exception, optionally using "nbdkit.set_error" first.
425
426 "extents"
427 (Optional)
428
429 def extents(h, count, offset, flags):
430 # return an iterable object (eg. list) of
431 # (offset, length, type) tuples:
432 return [ (off1, len1, type1), (off2, len2, type2), ... ]
433
434 Missing callbacks
435 Missing: "load" and "unload"
436 These are not needed because you can just use ordinary Python
437 constructs.
438
439 Missing: "name", "version", "longname", "description", "config_help",
440 "magic_config_key".
441 These are not yet supported.
442
444 $plugindir/nbdkit-python-plugin.so
445 The plugin.
446
447 Use "nbdkit --dump-config" to find the location of $plugindir.
448
450 "nbdkit-python-plugin" first appeared in nbdkit 1.2.
451
453 nbdkit(1), nbdkit-plugin(3), python(1).
454
456 Eric Blake
457
458 Richard W.M. Jones
459
460 Nir Soffer
461
463 Copyright (C) 2013-2021 Red Hat Inc.
464
466 Redistribution and use in source and binary forms, with or without
467 modification, are permitted provided that the following conditions are
468 met:
469
470 • Redistributions of source code must retain the above copyright
471 notice, this list of conditions and the following disclaimer.
472
473 • Redistributions in binary form must reproduce the above copyright
474 notice, this list of conditions and the following disclaimer in the
475 documentation and/or other materials provided with the
476 distribution.
477
478 • Neither the name of Red Hat nor the names of its contributors may
479 be used to endorse or promote products derived from this software
480 without specific prior written permission.
481
482 THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
483 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
484 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
485 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
486 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
487 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
488 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
489 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
490 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
491 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
492 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
493
494
495
496nbdkit-1.25.8 2021-05-25 nbdkit-python-plugin(3)