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.
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 an example plugin written in Python, see:
26       https://github.com/libguestfs/nbdkit/blob/master/plugins/python/example.py
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   Methods
107       Your script may use "import nbdkit" to have access to the following
108       methods in the "nbdkit" module:
109
110        nbdkit.set_error(err)
111
112       Record "err" as the reason you are about to throw an exception. "err"
113       should correspond to usual errno values, where it may help to "import
114       errno".
115
116   Exceptions
117       Python callbacks should throw exceptions to indicate errors.  Remember
118       to use "nbdkit.set_error" if you need to control which error is sent
119       back to the client; if omitted, the client will see an error of "EIO".
120
121   Python callbacks
122       This just documents the arguments to the callbacks in Python, and any
123       way that they differ from the C callbacks.  In all other respects they
124       work the same way as the C callbacks, so you should go and read
125       nbdkit-plugin(3).
126
127       "dump_plugin"
128           (Optional)
129
130           There are no arguments or return value.
131
132       "config"
133           (Optional)
134
135            def config(key, value):
136              # no return value
137
138       "config_complete"
139           (Optional)
140
141           There are no arguments or return value.
142
143       "get_ready"
144           (Optional)
145
146           There are no arguments or return value.
147
148       "open"
149           (Required)
150
151            def open(readonly):
152              # return handle
153
154           You can return any non-NULL Python value as the handle.  It is
155           passed back in subsequent calls.
156
157       "close"
158           (Optional)
159
160            def close(h):
161              # no return value
162
163           After "close" returns, the reference count of the handle is
164           decremented in the C part, which usually means that the handle and
165           its contents will be garbage collected.
166
167       "get_size"
168           (Required)
169
170            def get_size(h):
171              # return the size of the disk
172
173       "is_rotational"
174           (Optional)
175
176            def is_rotational(h):
177              # return a boolean
178
179       "can_multi_conn"
180           (Optional)
181
182            def can_multi_conn(h):
183              # return a boolean
184
185       "can_write"
186           (Optional)
187
188            def can_write(h):
189              # return a boolean
190
191       "can_flush"
192           (Optional)
193
194            def can_flush(h):
195              # return a boolean
196
197       "can_trim"
198           (Optional)
199
200            def can_trim(h):
201              # return a boolean
202
203       "can_zero"
204           (Optional)
205
206            def can_zero(h):
207              # return a boolean
208
209       "can_fast_zero"
210           (Optional)
211
212            def can_fast_zero(h):
213              # return a boolean
214
215       "can_fua"
216           (Optional)
217
218            def can_fua(h):
219              # return nbdkit.FUA_NONE or nbdkit.FUA_EMULATE
220              # or nbdkit.FUA_NATIVE
221
222       "can_cache"
223           (Optional)
224
225            def can_cache(h):
226              # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE
227              # or nbdkit.CACHE_NATIVE
228
229       "pread"
230           (Required)
231
232            def pread(h, buf, offset, flags):
233              # read into the buffer
234
235           The body of your "pread" function should read exactly "len(buf)"
236           bytes of data starting at disk "offset" and write it into the
237           buffer "buf".  "flags" is always 0.
238
239           NBD only supports whole reads, so your function should try to read
240           the whole region (perhaps requiring a loop).  If the read fails or
241           is partial, your function should throw an exception, optionally
242           using "nbdkit.set_error" first.
243
244       "pwrite"
245           (Optional)
246
247            def pwrite(h, buf, offset, flags):
248              length = len (buf)
249              # no return value
250
251           The body of your "pwrite" function should write the buffer "buf" to
252           the disk.  You should write "count" bytes to the disk starting at
253           "offset".  "flags" may contain "nbdkit.FLAG_FUA".
254
255           NBD only supports whole writes, so your function should try to
256           write the whole region (perhaps requiring a loop).  If the write
257           fails or is partial, your function should throw an exception,
258            optionally using "nbdkit.set_error" first.
259
260       "flush"
261           (Optional)
262
263            def flush(h, flags):
264              # no return value
265
266           The body of your "flush" function should do a sync(2) or
267           fdatasync(2) or equivalent on the backing store.  "flags" is always
268           0.
269
270           If the flush fails, your function should throw an exception,
271           optionally using "nbdkit.set_error" first.
272
273       "trim"
274           (Optional)
275
276            def trim(h, count, offset, flags):
277              # no return value
278
279           The body of your "trim" function should "punch a hole" in the
280           backing store.  "flags" may contain "nbdkit.FLAG_FUA".  If the trim
281           fails, your function should throw an exception, optionally using
282           "nbdkit.set_error" first.
283
284       "zero"
285           (Optional)
286
287            def zero(h, count, offset, flags):
288              # no return value
289
290           The body of your "zero" function should ensure that "count" bytes
291           of the disk, starting at "offset", will read back as zero.  "flags"
292           is a bitmask which may include "nbdkit.FLAG_MAY_TRIM",
293           "nbdkit.FLAG_FUA", "nbdkit.FLAG_FAST_ZERO".
294
295           NBD only supports whole writes, so your function should try to
296           write the whole region (perhaps requiring a loop).
297
298           If the write fails or is partial, your function should throw an
299           exception, optionally using "nbdkit.set_error" first.  In
300           particular, if you would like to automatically fall back to
301           "pwrite" (perhaps because there is nothing to optimize if
302           "flags & nbdkit.FLAG_MAY_TRIM" is false), use
303           "nbdkit.set_error (errno.EOPNOTSUPP)".
304
305       "cache"
306           (Optional)
307
308            def cache(h, count, offset, flags):
309              # no return value
310
311           The body of your "cache" function should prefetch data in the
312           indicated range.
313
314           If the cache operation fails, your function should throw an
315           exception, optionally using "nbdkit.set_error" first.
316
317   Missing callbacks
318       Missing: "load" and "unload"
319           These are not needed because you can just use ordinary Python
320           constructs.
321
322       Missing: "thread_model"
323           See "Threads" below.
324
325       Missing: "name", "version", "longname", "description", "config_help",
326       "magic_config_key", "can_extents", "extents".
327           These are not yet supported.
328
329   Threads
330       The thread model for Python callbacks currently cannot be set from
331       Python.  It is hard-coded in the C part to
332       "NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS".  This may change or be
333       settable in future.
334

FILES

336       $plugindir/nbdkit-python-plugin.so
337           The plugin.
338
339           Use "nbdkit --dump-config" to find the location of $plugindir.
340

VERSION

342       "nbdkit-python-plugin" first appeared in nbdkit 1.2.
343

SEE ALSO

345       nbdkit(1), nbdkit-plugin(3), python(1).
346

AUTHORS

348       Eric Blake
349
350       Richard W.M. Jones
351
352       Nir Soffer
353
355       Copyright (C) 2013-2019 Red Hat Inc.
356

LICENSE

358       Redistribution and use in source and binary forms, with or without
359       modification, are permitted provided that the following conditions are
360       met:
361
362       ·   Redistributions of source code must retain the above copyright
363           notice, this list of conditions and the following disclaimer.
364
365       ·   Redistributions in binary form must reproduce the above copyright
366           notice, this list of conditions and the following disclaimer in the
367           documentation and/or other materials provided with the
368           distribution.
369
370       ·   Neither the name of Red Hat nor the names of its contributors may
371           be used to endorse or promote products derived from this software
372           without specific prior written permission.
373
374       THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
375       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
376       IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
377       PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
378       LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
379       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
380       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
381       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
382       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
383       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
384       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
385
386
387
388nbdkit-1.18.4                     2020-04-16           nbdkit-python-plugin(3)
Impressum