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 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
336 $plugindir/nbdkit-python-plugin.so
337 The plugin.
338
339 Use "nbdkit --dump-config" to find the location of $plugindir.
340
342 "nbdkit-python-plugin" first appeared in nbdkit 1.2.
343
345 nbdkit(1), nbdkit-plugin(3), python(1).
346
348 Eric Blake
349
350 Richard W.M. Jones
351
352 Nir Soffer
353
355 Copyright (C) 2013-2019 Red Hat Inc.
356
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)