1nbdkit-sh-plugin(3) NBDKIT nbdkit-sh-plugin(3)
2
3
4
6 nbdkit-sh-plugin - nbdkit shell, script or executable plugin
7
9 nbdkit sh /path/to/script [arguments...]
10
11 nbdkit sh - <<'EOF'
12 ... shell script ...
13 EOF
14
16 "nbdkit-sh-plugin" allows you to write plugins for nbdkit(1) using
17 arbitrary scripting languages, including shells like bash(1), dash(1),
18 csh(1), zsh(1) etc., other scripting environments, or any executable.
19 Note if you want to use an established scripting language like Perl or
20 Python, then nbdkit has specific plugins to handle those languages and
21 those will be more efficient (see nbdkit(1) for a complete list).
22
23 If you have been given an nbdkit sh plugin
24 Assuming you have a shell script which is an nbdkit plugin, you run it
25 like this:
26
27 nbdkit sh /path/to/script
28
29 You may have to add further "key=value" arguments to the command line.
30 The script must be executable ("chmod +x").
31
32 Inline shell scripts
33 It is also possible to write a shell script plugin "inline" using "-"
34 as the name of the script, like this:
35
36 nbdkit sh - <<'EOF'
37 case "$1" in
38 get_size) echo 1M ;;
39 pread) dd if=/dev/zero count=$3 iflag=count_bytes ;;
40 *) exit 2 ;;
41 esac
42 EOF
43
44 By default the inline script runs under /bin/sh. You can add a shebang
45 ("#!") to use other scripting languages.
46
48 For an example plugin written in Bash, see:
49 https://github.com/libguestfs/nbdkit/blob/master/plugins/sh/example.sh
50
51 Broadly speaking, nbdkit shell plugins work like C ones, so you should
52 read nbdkit-plugin(3) first.
53
54 Programming model
55 This plugin has a simple programming model: For every plugin method
56 that needs to be called, the external script is invoked with parameters
57 describing the method and its arguments. The first parameter is always
58 the method name. For example:
59
60 /path/to/script config file disk.img
61 │ │ │
62 │ │ └─ value ($3)
63 │ └── key ($2)
64 method ($1)
65
66 /path/to/script pread <handle> <count> <offset>
67 │ │ │ │
68 │ │ │ └─ offset in bytes ($4)
69 │ │ └── request size in bytes ($3)
70 method ($1) └── handle ($2) ─ see "Handles" below
71
72 Exit codes
73 The script should exit with specific exit codes:
74
75 0 The method was executed successfully.
76
77 1 and 8-127
78 There was an error. The script may print on stderr an errno and a
79 message, for example:
80
81 ENOSPC Out of space
82
83 If the script doesn't print anything or the output cannot be parsed
84 then nbdkit assumes error "EIO".
85
86 2 The requested method is not supported by the script.
87
88 3 For methods which return booleans, this code indicates false.
89
90 4, 5, 6, 7
91 These exit codes are reserved for future use.
92
93 Temporary directory
94 A fresh script is invoked for each method call (ie. scripts are
95 stateless), so if the script needs to store state it has to store it
96 somewhere in the filesystem in a format and location which is left up
97 to the author of the script.
98
99 However nbdkit helps by creating a randomly named, empty directory for
100 the script. This directory persists for the lifetime of nbdkit and is
101 deleted when nbdkit exits. The name of the directory is passed to each
102 script invocation in the $tmpdir environment variable.
103
104 Handles
105 Handles are arbitrary strings, but it is best to limit them to short
106 alphanumeric strings.
107
108 Per-connection state
109
110 The temporary directory described above can be used for state for the
111 lifetime of the nbdkit instance (across multiple connections). If you
112 want to store state per connection then one way to do it is to create a
113 randomly named subdirectory under the temporary directory:
114
115 case "$1" in
116 ...
117 open)
118 mktemp -d $tmpdir/handle-XXXXXX ;;
119
120 The handle will be the subdirectory name, returned to the script as $2
121 in all connected calls (eg. "pread", "get_size"). You can delete the
122 subdirectory explicitly in "close":
123
124 case "$1" in
125 ...
126 close)
127 rm -rf "$2" ;;
128
129 or rely on nbdkit deleting the whole temporary directory including all
130 per-handle subdirectories when it exits.
131
132 Methods
133 This just documents the arguments to the script corresponding to each
134 plugin method, and any way that they differ from the C callbacks. In
135 all other respects they work the same way as the C callbacks, so you
136 should go and read nbdkit-plugin(3).
137
138 "load"
139 /path/to/script load
140
141 "unload"
142 /path/to/script unload
143
144 This is called just before nbdkit exits. Errors from this method
145 are ignored.
146
147 "dump_plugin"
148 /path/to/script dump_plugin
149
150 "config"
151 /path/to/script config <key> <value>
152
153 "config_complete"
154 /path/to/script config_complete
155
156 "open"
157 /path/to/script open <readonly>
158
159 The "readonly" parameter will be "true" or "false".
160
161 On success this should print the handle (any string) on stdout and
162 exit with code 0. If the handle ends with a newline character then
163 the newline is removed.
164
165 Unlike C plugins, this method is not required. If omitted then the
166 handle will be "" (empty string).
167
168 "close"
169 /path/to/script close <handle>
170
171 "get_size"
172 /path/to/script get_size <handle>
173
174 The script should print the size of the disk image on stdout. You
175 can print the size in bytes, or use any format understood by
176 "nbdkit_parse_size" such as "1M" (see "PARSING SIZE PARAMETERS" in
177 nbdkit-plugin(3)).
178
179 This method is required.
180
181 "can_write"
182 "can_flush"
183 "can_trim"
184 "can_zero"
185 "can_extents"
186 Unlike in other languages, you must provide the "can_*" methods
187 otherwise they are assumed to all return false and your "pwrite",
188 "flush", "trim", "zero" and "extents" methods will never be called.
189 The reason for this is obscure: In other languages we can detect if
190 (eg) a "pwrite" method is defined and synthesize an appropriate
191 response if no actual "can_write" method is defined. However
192 detecting if methods are present without running them is not
193 possible with this plugin.
194
195 /path/to/script can_write <handle>
196 /path/to/script can_flush <handle>
197 /path/to/script can_trim <handle>
198 /path/to/script can_zero <handle>
199 /path/to/script can_extents <handle>
200
201 The script should exit with code 0 for true or code 3 for false.
202
203 "is_rotational"
204 /path/to/script is_rotational <handle>
205
206 The script should exit with code 0 for true or code 3 for false.
207
208 "can_fua"
209 /path/to/script can_fua <handle>
210
211 This controls Forced Unit Access (FUA) behaviour of the core
212 server.
213
214 Unlike the other "can_*" callbacks, this one is not a boolean. It
215 must print either "none", "emulate" or "native" to stdout. The
216 meaning of these is described in nbdkit-plugin(3).
217
218 "can_multi_conn"
219 /path/to/script can_multi_conn <handle>
220
221 The script should exit with code 0 for true or code 3 for false.
222
223 "pread"
224 /path/to/script pread <handle> <count> <offset>
225
226 The script should print the requested binary data on stdout.
227 Exactly "count" bytes must be printed.
228
229 This method is required.
230
231 "pwrite"
232 /path/to/script pwrite <handle> <count> <offset> <flags>
233
234 The script should read the binary data to be written from stdin.
235
236 The "flags" parameter can be an empty string or "fua". In the
237 future, a comma-separated list of flags may be present.
238
239 Unlike in other languages, if you provide a "pwrite" method you
240 must also provide a "can_write" method which exits with code 0
241 (true).
242
243 "flush"
244 /path/to/script flush <handle>
245
246 Unlike in other languages, if you provide a "flush" method you must
247 also provide a "can_flush" method which exits with code 0 (true).
248
249 "trim"
250 /path/to/script trim <handle> <count> <offset> <flags>
251
252 The "flags" parameter can be an empty string or "fua". In the
253 future, a comma-separated list of flags may be present.
254
255 Unlike in other languages, if you provide a "trim" method you must
256 also provide a "can_trim" method which exits with code 0 (true).
257
258 "zero"
259 /path/to/script zero <handle> <count> <offset> <flags>
260
261 The "flags" parameter can be an empty string or a comma-separated
262 list of the flags: "fua" and "may_trim" (eg. "", "fua",
263 "fua,may_trim" are all possible values).
264
265 Unlike in other languages, if you provide a "zero" method you must
266 also provide a "can_zero" method which exits with code 0 (true).
267
268 "extents"
269 /path/to/script extents <handle> <count> <offset> <flags>
270
271 The "flags" parameter can be an empty string or "req_one".
272
273 This must print, one per line on stdout, a list of one or more
274 extents in the format:
275
276 offset length type
277
278 which correspond to the inputs of the C "nbdkit_add_extent"
279 function (see nbdkit-plugin(3)). The "offset" and "length" fields
280 may use any format understood by "nbdkit_parse_size". The optional
281 "type" field may be an integer, missing (same as 0), or a comma-
282 separated list of the words "hole" and "zero". An example of a
283 valid set of extents covering a "10M" disk where the first megabyte
284 only is allocated data:
285
286 0 1M
287 1M 9M hole,zero
288
289 Unlike in other languages, if you provide an "extents" method you
290 must also provide a "can_extents" method which exits with code 0
291 (true).
292
293 Missing callbacks
294 Missing: "name", "version", "longname", "description", "config_help"
295 These are not yet supported.
296
297 Threads
298 The thread model for scripts currently cannot be set from this plugin.
299 It is hard-coded in the C part to
300 "NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS". This may change or be
301 settable in future.
302
304 nbdkit(1), nbdkit-plugin(3).
305
307 Richard W.M. Jones
308
310 Copyright (C) 2018 Red Hat Inc.
311
313 Redistribution and use in source and binary forms, with or without
314 modification, are permitted provided that the following conditions are
315 met:
316
317 · Redistributions of source code must retain the above copyright
318 notice, this list of conditions and the following disclaimer.
319
320 · Redistributions in binary form must reproduce the above copyright
321 notice, this list of conditions and the following disclaimer in the
322 documentation and/or other materials provided with the
323 distribution.
324
325 · Neither the name of Red Hat nor the names of its contributors may
326 be used to endorse or promote products derived from this software
327 without specific prior written permission.
328
329 THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
330 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
331 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
332 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
333 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
334 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
335 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
336 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
337 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
338 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
339 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
340
341
342
343nbdkit-1.12.3 2019-05-21 nbdkit-sh-plugin(3)