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 def open(readonly):
36 # see below
37 def get_size(h):
38 # see below
39 def pread(h, count, offset):
40 # see below
41
42 Note that the subroutines must have those literal names (like "open"),
43 because the C part looks up and calls those functions directly. You
44 may want to include documentation and globals (eg. for storing global
45 state). Any other top level statements are run when the script is
46 loaded, just like ordinary Python.
47
48 Python versions
49 In nbdkit ≤ 1.14, either Python 2 or 3 could be used. It was selected
50 at compile time by either:
51
52 ./configure
53
54 which selected the version of Python by looking at the "python"
55 interpreter found on the $PATH. Or:
56
57 ./configure PYTHON=/usr/bin/python3
58
59 which allowed you to select a different interpreter and hence a
60 different version of Python.
61
62 nbdkit ≥ 1.16 drops all support for Python 2, since Python 2 has
63 reached its end of life.
64
65 The new behaviour is that "./configure" looks for "python3" or "python"
66 (in that order) on the $PATH. It will fail if the first interpreter it
67 finds is a Python 2 interpreter. You may also still choose a Python
68 interpreter by setting the "PYTHON" variable at configure time as
69 above.
70
71 If you wish to continue using nbdkit plugins written in Python 2 then
72 you must use nbdkit ≤ 1.14, but we would advise you to update your
73 plugins.
74
75 To find out which version the Python plugin was compiled for, use the
76 --dump-plugin option, eg:
77
78 $ nbdkit python --dump-plugin
79 ...
80 python_version=3.7.0
81 python_pep_384_abi_version=3
82
83 Executable script
84 If you want you can make the script executable and include a "shebang"
85 at the top:
86
87 #!/usr/sbin/nbdkit python
88
89 See also "Shebang scripts" in nbdkit(1).
90
91 These scripts can also be installed in the $plugindir. See "WRITING
92 PLUGINS IN OTHER PROGRAMMING LANGUAGES" in nbdkit-plugin(3).
93
94 Methods
95 Your script may use "import nbdkit" to have access to the following
96 methods in the "nbdkit" module:
97
98 nbdkit.set_error(err)
99
100 Record "err" as the reason you are about to throw an exception. "err"
101 should correspond to usual errno values, where it may help to "import
102 errno".
103
104 Exceptions
105 Python callbacks should throw exceptions to indicate errors. Remember
106 to use "nbdkit.set_error" if you need to control which error is sent
107 back to the client; if omitted, the client will see an error of "EIO".
108
109 Python callbacks
110 This just documents the arguments to the callbacks in Python, and any
111 way that they differ from the C callbacks. In all other respects they
112 work the same way as the C callbacks, so you should go and read
113 nbdkit-plugin(3).
114
115 "dump_plugin"
116 (Optional)
117
118 There are no arguments or return value.
119
120 "config"
121 (Optional)
122
123 def config(key, value):
124 # no return value
125
126 "config_complete"
127 (Optional)
128
129 There are no arguments or return value.
130
131 "open"
132 (Required)
133
134 def open(readonly):
135 # return handle
136
137 You can return any non-NULL Python value as the handle. It is
138 passed back in subsequent calls.
139
140 "close"
141 (Optional)
142
143 def close(h):
144 # no return value
145
146 After "close" returns, the reference count of the handle is
147 decremented in the C part, which usually means that the handle and
148 its contents will be garbage collected.
149
150 "get_size"
151 (Required)
152
153 def get_size(h):
154 # return the size of the disk
155
156 "is_rotational"
157 (Optional)
158
159 def is_rotational(h):
160 # return a boolean
161
162 "can_write"
163 (Optional)
164
165 def can_write(h):
166 # return a boolean
167
168 "can_flush"
169 (Optional)
170
171 def can_flush(h):
172 # return a boolean
173
174 "can_trim"
175 (Optional)
176
177 def can_trim(h):
178 # return a boolean
179
180 "pread"
181 (Required)
182
183 def pread(h, count, offset):
184 # construct a buffer of length count bytes and return it
185
186 The body of your "pread" function should construct a buffer of
187 length (at least) "count" bytes. You should read "count" bytes
188 from the disk starting at "offset".
189
190 The returned buffer can be any type compatible with the Python 3
191 buffer protocol, such as bytearray, bytes or memoryview
192 (https://docs.python.org/3/c-api/buffer.html)
193
194 NBD only supports whole reads, so your function should try to read
195 the whole region (perhaps requiring a loop). If the read fails or
196 is partial, your function should throw an exception, optionally
197 using "nbdkit.set_error" first.
198
199 "pwrite"
200 (Optional)
201
202 def pwrite(h, buf, offset):
203 length = len (buf)
204 # no return value
205
206 The body of your "pwrite" function should write the buffer "buf" to
207 the disk. You should write "count" bytes to the disk starting at
208 "offset".
209
210 NBD only supports whole writes, so your function should try to
211 write the whole region (perhaps requiring a loop). If the write
212 fails or is partial, your function should throw an exception,
213 optionally using "nbdkit.set_error" first.
214
215 "flush"
216 (Optional)
217
218 def flush(h):
219 # no return value
220
221 The body of your "flush" function should do a sync(2) or
222 fdatasync(2) or equivalent on the backing store.
223
224 If the flush fails, your function should throw an exception,
225 optionally using "nbdkit.set_error" first.
226
227 "trim"
228 (Optional)
229
230 def trim(h, count, offset):
231 # no return value
232
233 The body of your "trim" function should "punch a hole" in the
234 backing store. If the trim fails, your function should throw an
235 exception, optionally using "nbdkit.set_error" first.
236
237 "zero"
238 (Optional)
239
240 def zero(h, count, offset, may_trim):
241 # no return value
242
243 The body of your "zero" function should ensure that "count" bytes
244 of the disk, starting at "offset", will read back as zero. If
245 "may_trim" is true, the operation may be optimized as a trim as
246 long as subsequent reads see zeroes.
247
248 NBD only supports whole writes, so your function should try to
249 write the whole region (perhaps requiring a loop). If the write
250 fails or is partial, your function should throw an exception,
251 optionally using "nbdkit.set_error" first. In particular, if you
252 would like to automatically fall back to "pwrite" (perhaps because
253 there is nothing to optimize if "may_trim" is false), use
254 "nbdkit.set_error(errno.EOPNOTSUPP)".
255
256 Missing callbacks
257 Missing: "load" and "unload"
258 These are not needed because you can just use ordinary Python
259 constructs.
260
261 Missing: "thread_model"
262 See "Threads" below.
263
264 Missing: "name", "version", "longname", "description", "config_help",
265 "magic_config_key", "can_fua", "can_cache", "can_zero",
266 "can_fast_zero", "can_extents", "can_multi_conn", "cache", "extents".
267 These are not yet supported.
268
269 Threads
270 The thread model for Python callbacks currently cannot be set from
271 Python. It is hard-coded in the C part to
272 "NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS". This may change or be
273 settable in future.
274
276 $plugindir/nbdkit-python-plugin.so
277 The plugin.
278
279 Use "nbdkit --dump-config" to find the location of $plugindir.
280
282 "nbdkit-python-plugin" first appeared in nbdkit 1.2.
283
285 nbdkit(1), nbdkit-plugin(3), python(1).
286
288 Eric Blake
289
290 Richard W.M. Jones
291
292 Nir Soffer
293
295 Copyright (C) 2013-2019 Red Hat Inc.
296
298 Redistribution and use in source and binary forms, with or without
299 modification, are permitted provided that the following conditions are
300 met:
301
302 · Redistributions of source code must retain the above copyright
303 notice, this list of conditions and the following disclaimer.
304
305 · Redistributions in binary form must reproduce the above copyright
306 notice, this list of conditions and the following disclaimer in the
307 documentation and/or other materials provided with the
308 distribution.
309
310 · Neither the name of Red Hat nor the names of its contributors may
311 be used to endorse or promote products derived from this software
312 without specific prior written permission.
313
314 THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
315 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
316 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
317 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
318 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
319 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
320 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
321 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
322 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
323 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
324 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325
326
327
328nbdkit-1.16.1 2019-12-03 nbdkit-python-plugin(3)