1nbdkit-sh-plugin(3)                 NBDKIT                 nbdkit-sh-plugin(3)
2
3
4

NAME

6       nbdkit-sh-plugin - nbdkit shell, script or executable plugin
7

SYNOPSIS

9        nbdkit sh /path/to/script [arguments...]
10
11        nbdkit sh - <<'EOF'
12        ... shell script ...
13        EOF
14

DESCRIPTION

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

WRITING AN NBDKIT SH PLUGIN

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       Scripts should ignore extra parameters that they don't understand since
73       we may add new parameters in future.
74
75   Exit codes
76       The script should exit with specific exit codes:
77
78       0   The method was executed successfully.
79
80       1 and 8-127
81           There was an error.  The script may print on stderr an errno name,
82           optionally followed by whitespace and a message, for example:
83
84            ENOSPC Out of space
85
86           If the script doesn't print anything or the output cannot be parsed
87           then nbdkit assumes error "EIO".  Note that output to stderr is
88           ignored if the command succeeds, so it is acceptable to output a
89           potential error message prefix prior to attempting a command which
90           will add further details if a failure occurs.
91
92       2   The requested method is not supported by the script.
93
94       3   For methods which return booleans, this code indicates false.
95
96       4, 5, 6, 7
97           These exit codes are reserved for future use.
98
99   Temporary directory
100       A fresh script is invoked for each method call (ie. scripts are
101       stateless), so if the script needs to store state it has to store it
102       somewhere in the filesystem in a format and location which is left up
103       to the author of the script.
104
105       However nbdkit helps by creating a randomly named, empty directory for
106       the script.  This directory persists for the lifetime of nbdkit and is
107       deleted when nbdkit exits.  The name of the directory is passed to each
108       script invocation in the $tmpdir environment variable.
109
110   Handles
111       Handles are arbitrary strings, but it is best to limit them to short
112       alphanumeric strings.
113
114       Per-connection state
115
116       The temporary directory described above can be used for state for the
117       lifetime of the nbdkit instance (across multiple connections).  If you
118       want to store state per connection then one way to do it is to create a
119       randomly named subdirectory under the temporary directory:
120
121        case "$1" in
122          ...
123          open)
124            mktemp -d $tmpdir/handle-XXXXXX ;;
125
126       The handle will be the subdirectory name, returned to the script as $2
127       in all connected calls (eg. "pread", "get_size").  You can delete the
128       subdirectory explicitly in "close":
129
130        case "$1" in
131          ...
132          close)
133            rm -rf "$2" ;;
134
135       or rely on nbdkit deleting the whole temporary directory including all
136       per-handle subdirectories when it exits.
137
138   Performance
139       This plugin has to fork on every request, so performance will never be
140       great.  For best performance, consider using the nbdkit-plugin(3) API
141       directly.  Having said that, if you have a sh plugin and want to
142       improve performance then the following tips may help:
143
144       Relax the thread model.
145           The default "thread_model" is "serialize_all_requests" meaning that
146           two instances of the script can never be running at the same time.
147           This is safe but slow.  If your script is safe to be called in
148           parallel, set this to "parallel".
149
150       Implement the "zero" method.
151           If the "zero" method is not implemented then nbdkit will fall back
152           to using "pwrite" which is considerably slower because nbdkit has
153           to send blocks of zeroes to the script.
154
155       You don't have to write shell scripts.
156           This plugin can run any external binary, not only shell scripts.
157           You should get more performance by rewriting the shell script as a
158           program in a compiled language.
159
160   Methods
161       This just documents the arguments to the script corresponding to each
162       plugin method, and any way that they differ from the C callbacks.  In
163       all other respects they work the same way as the C callbacks, so you
164       should go and read nbdkit-plugin(3).
165
166       "load"
167            /path/to/script load
168
169       "unload"
170            /path/to/script unload
171
172           This is called just before nbdkit exits.  Errors from this method
173           are ignored.
174
175       "dump_plugin"
176            /path/to/script dump_plugin
177
178       "config"
179            /path/to/script config <key> <value>
180
181       "config_complete"
182            /path/to/script config_complete
183
184       "magic_config_key"
185            /path/to/script magic_config_key
186
187           If a magic config key is needed, this should echo it to stdout.
188           See "Magic parameters" in nbdkit(1).
189
190       "thread_model"
191            /path/to/script thread_model
192
193           On success this should print the desired thread model of the
194           script, one of "serialize_connections", "serialize_all_requests",
195           "serialize_requests", or "parallel".
196
197           This method is not required; if omitted, then the plugin will be
198           executed under the safe "serialize_all_requests" model.  However,
199           this means that this method must be provided if you want to use the
200           "parallel" or "serialize_requests" model.  Even then your request
201           may be restricted for other reasons; look for "thread_model" in the
202           output of "nbdkit --dump-plugin sh script" to see what actually
203           gets selected.
204
205           If an error occurs, the script should output an error message and
206           exit with status 1; unrecognized output is ignored.
207
208       "open"
209            /path/to/script open <readonly> <exportname>
210
211           The "readonly" parameter will be "true" or "false".  The
212           "exportname" parameter, if present, is the export name passed to
213           the server from the client.
214
215           On success this should print the handle (any string) on stdout and
216           exit with code 0.  If the handle ends with a newline character then
217           the newline is removed.
218
219           Unlike C plugins, this method is not required.  If omitted then the
220           handle will be "" (empty string).
221
222       "close"
223            /path/to/script close <handle>
224
225       "get_size"
226            /path/to/script get_size <handle>
227
228           The script should print the size of the disk image on stdout.  You
229           can print the size in bytes, or use any format understood by
230           "nbdkit_parse_size" such as "1M" (see "PARSING SIZE PARAMETERS" in
231           nbdkit-plugin(3)).
232
233           This method is required.
234
235       "can_write"
236       "can_flush"
237       "can_trim"
238       "can_zero"
239       "can_extents"
240           Unlike in other languages, you must provide the "can_*" methods
241           otherwise they are assumed to all return false and your "pwrite",
242           "flush", "trim", "zero" and "extents" methods will never be called.
243           The reason for this is obscure: In other languages we can detect if
244           (eg) a "pwrite" method is defined and synthesize an appropriate
245           response if no actual "can_write" method is defined.  However
246           detecting if methods are present without running them is not
247           possible with this plugin.
248
249            /path/to/script can_write <handle>
250            /path/to/script can_flush <handle>
251            /path/to/script can_trim <handle>
252            /path/to/script can_zero <handle>
253            /path/to/script can_extents <handle>
254
255           The script should exit with code 0 for true or code 3 for false.
256
257       "is_rotational"
258       "can_fast_zero"
259            /path/to/script is_rotational <handle>
260            /path/to/script can_fast_zero <handle>
261
262           The script should exit with code 0 for true or code 3 for false.
263
264       "can_fua"
265       "can_cache"
266            /path/to/script can_fua <handle>
267            /path/to/script can_cache <handle>
268
269           These control Forced Unit Access (FUA) and caching behaviour of the
270           core server.
271
272           Unlike the other "can_*" callbacks, these two are not a boolean.
273           They must print either "none", "emulate" or "native" to stdout.
274           The meaning of these is described in nbdkit-plugin(3).
275           Furthermore, you must provide a "can_cache" method if you desire
276           the "cache" callback to be utilized, similar to the reasoning
277           behind requiring "can_write" to utilize "pwrite".
278
279       "can_multi_conn"
280            /path/to/script can_multi_conn <handle>
281
282           The script should exit with code 0 for true or code 3 for false.
283
284       "pread"
285            /path/to/script pread <handle> <count> <offset>
286
287           The script should print the requested binary data on stdout.
288           Exactly "count" bytes must be printed.
289
290           This method is required.
291
292       "pwrite"
293            /path/to/script pwrite <handle> <count> <offset> <flags>
294
295           The script should read the binary data to be written from stdin.
296
297           The "flags" parameter can be an empty string or "fua".  In the
298           future, a comma-separated list of flags may be present.
299
300           Unlike in other languages, if you provide a "pwrite" method you
301           must also provide a "can_write" method which exits with code 0
302           (true).
303
304       "flush"
305            /path/to/script flush <handle>
306
307           Unlike in other languages, if you provide a "flush" method you must
308           also provide a "can_flush" method which exits with code 0 (true).
309
310       "trim"
311            /path/to/script trim <handle> <count> <offset> <flags>
312
313           The "flags" parameter can be an empty string or "fua".  In the
314           future, a comma-separated list of flags may be present.
315
316           Unlike in other languages, if you provide a "trim" method you must
317           also provide a "can_trim" method which exits with code 0 (true).
318
319       "zero"
320            /path/to/script zero <handle> <count> <offset> <flags>
321
322           The "flags" parameter can be an empty string or a comma-separated
323           list of the flags: "fua", "may_trim", and "fast" (eg. "", "fua",
324           "fua,may_trim,fast" are some of the 8 possible values).
325
326           Unlike in other languages, if you provide a "zero" method you must
327           also provide a "can_zero" method which exits with code 0 (true).
328
329           To trigger a fallback to <pwrite> on a normal zero request, or to
330           respond quickly to the "fast" flag that a specific zero request is
331           no faster than a corresponding write, the script must output
332           "ENOTSUP" or "EOPNOTSUPP" to stderr (possibly followed by a
333           description of the problem) before exiting with code 1 (failure).
334
335       "extents"
336            /path/to/script extents <handle> <count> <offset> <flags>
337
338           The "flags" parameter can be an empty string or "req_one".
339
340           This must print, one per line on stdout, a list of one or more
341           extents in the format:
342
343            offset length type
344
345           which correspond to the inputs of the C "nbdkit_add_extent"
346           function (see nbdkit-plugin(3)).  The "offset" and "length" fields
347           may use any format understood by "nbdkit_parse_size".  The optional
348           "type" field may be an integer, missing (same as 0), or a comma-
349           separated list of the words "hole" and "zero".  An example of a
350           valid set of extents covering a "10M" disk where the first megabyte
351           only is allocated data:
352
353            0  1M
354            1M 9M  hole,zero
355
356           Unlike in other languages, if you provide an "extents" method you
357           must also provide a "can_extents" method which exits with code 0
358           (true).
359
360       "cache"
361            /path/to/script cache <handle> <count> <offset>
362
363           Unlike in other languages, if you provide a "cache" method you must
364           also provide a "can_cache" method which prints "native" and exits
365           with code 0 (true).
366
367   Missing callbacks
368       Missing: "name", "version", "longname", "description", "config_help"
369           These are not yet supported.
370

FILES

372       $plugindir/nbdkit-sh-plugin.so
373           The plugin.
374
375           Use "nbdkit --dump-config" to find the location of $plugindir.
376

VERSION

378       "nbdkit-sh-plugin" first appeared in nbdkit 1.8.
379

SEE ALSO

381       nbdkit(1), nbdkit-plugin(3).
382

AUTHORS

384       Richard W.M. Jones
385
387       Copyright (C) 2018-2019 Red Hat Inc.
388

LICENSE

390       Redistribution and use in source and binary forms, with or without
391       modification, are permitted provided that the following conditions are
392       met:
393
394       ·   Redistributions of source code must retain the above copyright
395           notice, this list of conditions and the following disclaimer.
396
397       ·   Redistributions in binary form must reproduce the above copyright
398           notice, this list of conditions and the following disclaimer in the
399           documentation and/or other materials provided with the
400           distribution.
401
402       ·   Neither the name of Red Hat nor the names of its contributors may
403           be used to endorse or promote products derived from this software
404           without specific prior written permission.
405
406       THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY
407       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
408       IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
409       PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE
410       LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
411       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
412       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
413       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
414       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
415       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
416       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
417
418
419
420nbdkit-1.16.1                     2019-12-03               nbdkit-sh-plugin(3)
Impressum