[PATCH nbdkit 0/2] Temporarily remove .list_exports for nbdkit 1.22
by Richard W.M. Jones
If you're following nbdkit development upstream you'll have seen that
we are still making changes to the .list_exports and related APIs.
The current .list_exports API upstream is not how it will look
finally. The latest set of proposals was here:
https://www.redhat.com/archives/libguestfs/2020-August/thread.html#00330
At the same time I'd like to do an nbdkit 1.22 (stable) release.
There are a few reasons for this, some good and some not so great:
- We have sufficient new features and the schedule is right to do a
release, but I don't want to push large changes in at the last
minute.
- The VDDK plugin has several vital fixes which will be appreciated
by anyone using nbdkit to access VMware.
- The Windows patches could be added _after_ we do the stable release
so they have plenty of time to sit in development. At the moment I
have to keep rebasing them.
- (The not so good one) RHEL 8 demands that we either rebase nbdkit
now, as in _today_, or else we will wait for many months before our
customers can use the new features.
Therefore I propose the two following patches. The first one removes
the mention of list_exports and nbdkit*export* APIs from the 1.22
release notes.
The second one is for stable-1.22 only (before 1.22.0 goes out). It
removes the .list_exports feature from plugins. It also removes the
nbdkit*export* APIs from <nbdkit-plugin.h> (ie. the public API). This
doesn't affect development, it would only be for the 1.22 release.
Rich.
4 years, 1 month
[supermin PATCH] rpm: check for SQLite-based RPM DB
by Pino Toscano
Fedora 33 switched the DB of RPM to SQLite, so no more Packages/Name/etc
files. Because any missing file exception is ignored when checking for
--if-newer, the lack of the Package files was not properly noticed, so
the appliance was always considered out out date.
Check for the SQLite-based DB first, falling back to the old format.
Signed-off-by: Pino Toscano <ptoscano(a)redhat.com>
---
src/ph_rpm.ml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/ph_rpm.ml b/src/ph_rpm.ml
index dbe3bda..0821126 100644
--- a/src/ph_rpm.ml
+++ b/src/ph_rpm.ml
@@ -234,7 +234,10 @@ let rpm_package_name pkg =
rpm.name
let rpm_get_package_database_mtime () =
- (lstat "/var/lib/rpm/Packages").st_mtime
+ try
+ (lstat "/var/lib/rpm/rpmdb.sqlite").st_mtime
+ with Unix_error (ENOENT, _, _) ->
+ (lstat "/var/lib/rpm/Packages").st_mtime
(* Return the best provider of a particular RPM requirement.
*
--
2.26.2
4 years, 1 month
[nbdkit PATCH 0/5] Implement .default_export, nbdkit_string_intern
by Eric Blake
More patches on the way for improving .list_exports signature and
adding .export_description, but this is the promised code showing
why nbdkit_string_intern is useful. Patch 4 is somewhat RFC: we
could either add new API to take the boilerplate from:
foo_config(const char *key, const char *value) {
if (strcmp (key, "file") == 0) {
CLEANUP_FREE char *tmp = nbdkit_realpath (value);
filename = nbdkit_string_intern (tmp);
if (!filename)
return -1;
}
...
to the shorter:
foo_config(const char *key, const char *value) {
if (strcmp (key, "file") == 0) {
if ((filename = nbdkit_realpath_intern (value)) == NULL)
return -1;
}
by adding 'const char *nbdkit_realpath_intern(const char *name)',
or maybe we instead add a 'bool malloced' knob to nbdkit_string_intern,
passing true transfers ownership of an existing string, and passing
false forces nbdkit to copy (but exposes a bit more of a malloc/free
coupling between plugin and nbdkit):
foo_config(const char *key, const char *value) {
if (strcmp (key, "file") == 0) {
if ((filename = nbdkit_string_intern (nbdkit_realpath (value),
true)) == NULL)
return -1;
}
Also, more than just the file plugin shares the pattern of copying
off a config name where we could simplify or eliminate .unload by
interning the string.
Eric Blake (5):
api: Add .default_export
server: Respond to NBD_INFO_NAME request
api: Add nbdkit_string_intern helper
file: Utilize nbdkit_string_intern
sh, eval: Implement .default_export
docs/nbdkit-filter.pod | 37 ++++++---
docs/nbdkit-plugin.pod | 66 +++++++++++++++-
plugins/eval/nbdkit-eval-plugin.pod | 2 +
plugins/sh/nbdkit-sh-plugin.pod | 20 ++++-
include/nbdkit-common.h | 2 +
include/nbdkit-filter.h | 9 ++-
include/nbdkit-plugin.h | 1 +
tests/Makefile.am | 4 +-
server/internal.h | 14 +++-
server/backend.c | 45 +++++++----
server/connections.c | 2 +-
server/exports.c | 8 +-
server/filters.c | 12 +++
server/main.c | 27 ++-----
server/nbdkit.syms | 1 +
server/plugins.c | 33 +++++---
server/protocol-handshake-newstyle.c | 68 ++++++++++++++--
server/public.c | 42 ++++++++++
plugins/sh/methods.h | 1 +
plugins/eval/eval.c | 2 +
plugins/file/file.c | 20 ++---
plugins/ondemand/ondemand.c | 11 ++-
plugins/sh/methods.c | 54 ++++++++++++-
plugins/sh/sh.c | 1 +
plugins/sh/example.sh | 2 +-
filters/log/log.c | 10 +--
filters/tls-fallback/tls-fallback.c | 12 ++-
tests/test-eval-exports.sh | 34 +++++---
tests/test-export-info.sh | 114 +++++++++++++++++++++++++++
tests/test-tls-fallback.sh | 11 ++-
tests/test-layers-filter.c | 9 +++
tests/test-layers-plugin.c | 8 ++
tests/test-layers.c | 24 +++---
33 files changed, 573 insertions(+), 133 deletions(-)
create mode 100755 tests/test-export-info.sh
--
2.28.0
4 years, 1 month
[PATCH v2] v2v: fix UEFI bootloader for linux guests
by Denis Plotnikov
v2:
Rich, I hope I've done all modifications according to your comments, namely:
* moved the code from linux_bootloaders to convert_linux
* made minor code modifications
---
Not all UEFI guests can survive conversion, because of lost bootloader
information in UEFI NVRAM. But some guest can cope with this because they
have a fallback bootloader and use UEFI Removable Media Boot Behavior to load
(see https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_A_Feb14.pdf
3.5.1.1 Removable Media Boot Behavior). If UEFI firmware can't find
a bootloader in its settings it uses the removable media boot behavior to
find a bootloader.
We can fix the guests which don't have such a fallback loader by providing
a temporary one. This bootloader is used for the first boot only, then the
conversion script restores the initial bootloader settings and removes the
temporary loader.
Signed-off-by: Denis Plotnikov <dplotnikov(a)virtuozzo.com>
---
v2v/convert_linux.ml | 123 ++++++++++++++++++++++++++++++++++++++
v2v/linux_bootloaders.ml | 7 +++
v2v/linux_bootloaders.mli | 4 ++
3 files changed, 134 insertions(+)
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index e91ae120f..045afa98b 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -1122,6 +1122,129 @@ shutdown -h -P +0
Linux.augeas_reload g
);
+ (* Some linux uefi setups can't boot after conversion because of
+ lost uefi boot entries. The uefi boot entries are stored in uefi
+ NVRAM. The NVRAM content isn't a part of vm disk content and
+ usualy can't be converted alongside the vm.
+ If a vm doesn't have uefi fallback path (/EFI/BOOT/BOOT<arch>.efi)
+ the vm is unbootable after conversion.
+ The following code tries to make an uefi fallback path for
+ a uefi linux vm.
+ *)
+ match inspect.i_firmware with
+ | I_UEFI _ -> (
+ (* Standard uefi fallback path *)
+ let uefi_fallback_path = "/boot/efi/EFI/BOOT/" in
+
+ (* Helper function checks if 'source' contains 's' *)
+ let contains source s = (
+ let re = Str.regexp_string s in
+ try
+ ignore (Str.search_forward re source 0);
+ true
+ with Not_found -> false
+ ) in
+
+ let cant_fix_uefi () =
+ info (f_"Can't fix UEFI bootloader. VM may not boot.")
+ in
+
+ let get_uefi_arch_suffix = function
+ | "x86_64" -> Some "X64"
+ | "x86_32" -> Some "X32"
+ | _ -> None
+ in
+
+ match get_uefi_arch_suffix inspect.i_arch with
+ | None -> cant_fix_uefi ()
+ | Some suffix -> (
+ let uefi_fallback_name =
+ sprintf "%sBOOT%s.EFI" uefi_fallback_path suffix in
+
+ let file_exists file =
+ if g#exists file then
+ true
+ else (
+ info (f_"Can't find file: '%s' needed for UEFI fixing")
+ file;
+ false )
+ in
+
+ let grub_config = bootloader#get_config_file () in
+
+ let grub_path =
+ String.sub grub_config 0 (String.rindex grub_config '/') in
+
+ if g#exists uefi_fallback_name then
+ (* don't do anything if uefi fallback exists *)
+ ()
+ else (
+ info (f_"Fixing UEFI bootloader.");
+ match inspect.i_distro, inspect.i_major_version with
+ | "centos", 6 ->
+ (* to make a bootable uefi centos 6 we need to
+ * copy grub.efi and grub.conf to UEFI fallback path
+ * and rename them to BOOT<arch>.efi and BOOT<arch>.conf
+ * correspondingly *)
+ let uefi_grub_name = String.concat "" [grub_path; "/grub.efi"] in
+ let uefi_grub_conf = String.concat "" [
+ String.sub uefi_fallback_name 0
+ (String.rindex uefi_fallback_name '.');
+ ".conf" ] in
+ if file_exists uefi_grub_name && file_exists grub_config then (
+ g#mkdir_p uefi_fallback_path;
+ g#cp uefi_grub_name uefi_fallback_name;
+ g#cp grub_config uefi_grub_conf;
+ let fix_script = sprintf
+"#!/bin/bash
+efibootmgr -c -L \"CentOS 6\"
+rm -rf %s" uefi_fallback_path in
+ Firstboot.add_firstboot_script
+ g inspect.i_root "fix uefi boot" fix_script)
+ else
+ cant_fix_uefi ()
+ | "ubuntu", 14 ->
+ (* to make a bootable uefi ubuntu 14 we need to
+ * copy shim<arch>.efi to UEFI fallback path
+ * and rename it to BOOT<arch>.efi, also we copy
+ * grub.efi and grub.cfg to UEFI fallback path without renaming *)
+ let arch_suffix = String.lowercase_ascii suffix in
+
+ let shim =
+ String.concat "" [grub_path; "/shim"; arch_suffix; ".efi"] in
+ let uefi_grub_name =
+ String.concat "" [grub_path; "/grub"; arch_suffix; ".efi"] in
+
+ if file_exists shim && file_exists uefi_grub_name
+ && file_exists grub_config then (
+ g#mkdir_p uefi_fallback_path;
+ g#cp shim uefi_fallback_name;
+ g#cp uefi_grub_name uefi_fallback_path;
+ g#cp grub_config uefi_fallback_path;
+ (* if the shim is at the standard path, clean up uefi fixing
+ * if not, then just don't clean up and leave the temp loader
+ * at UEFI fallback path for simplicity
+ *)
+ if contains shim "/boot/efi/EFI/ubuntu/shim" then
+ let fix_script = sprintf
+"#!/bin/bash
+sudo efibootmgr -c -L ubuntu -l \\\\EFI\\\\ubuntu\\\\shim%s.efi
+rm -rf %s" arch_suffix uefi_fallback_path in
+ Firstboot.add_firstboot_script
+ g inspect.i_root "fix uefi boot" fix_script
+ else
+ ())
+ else
+ cant_fix_uefi ()
+ | _, _ ->
+ info (f_"No UEFI fix rule for %s %d")
+ inspect.i_distro inspect.i_major_version;
+ cant_fix_uefi ()
+ )
+ )
+ )
+ | I_BIOS -> ();
+
(* Delete blkid caches if they exist, since they will refer to the old
* device names. blkid will rebuild these on demand.
*
diff --git a/v2v/linux_bootloaders.ml b/v2v/linux_bootloaders.ml
index de3d107e9..4ca28782b 100644
--- a/v2v/linux_bootloaders.ml
+++ b/v2v/linux_bootloaders.ml
@@ -36,6 +36,7 @@ class virtual bootloader = object
method virtual configure_console : unit -> unit
method virtual remove_console : unit -> unit
method update () = ()
+ method virtual get_config_file : unit -> string
end
(* Helper function for SUSE: remove (hdX,X) prefix from a path. *)
@@ -184,6 +185,9 @@ object
loop paths;
g#aug_save ()
+
+ method get_config_file () =
+ grub_config
end
(** The method used to get and set the default kernel in Grub2. *)
@@ -342,6 +346,9 @@ object (self)
method update () =
ignore (g#command [| grub2_mkconfig_cmd; "-o"; grub_config |])
+
+ method get_config_file () =
+ grub_config
end
(* Helper type used in detect_bootloader. *)
diff --git a/v2v/linux_bootloaders.mli b/v2v/linux_bootloaders.mli
index 30cdfe3c7..d9f0be8e1 100644
--- a/v2v/linux_bootloaders.mli
+++ b/v2v/linux_bootloaders.mli
@@ -44,6 +44,10 @@ class virtual bootloader : object
(** Update the bootloader: For grub2 only this runs the
[grub2-mkconfig] command to rebuild the configuration. This
is not necessary for grub-legacy. *)
+
+ method virtual get_config_file : unit -> string
+ (** Returns the path to the bootloader config file,
+ e.g /boot/grub/grub.cfg *)
end
(** Encapsulates a Linux boot loader as object. *)
--
2.17.0
4 years, 1 month
ANNOUNCE: libnbd 1.4 - high performance NBD client library
by Richard W.M. Jones
I'm pleased to announce the release of libnbd 1.4.0,
a high performance Network Block Device (NBD) client library.
Key features of libnbd:
* Synchronous API for ease of use.
* Asynchronous API for writing non-blocking, multithreaded clients.
You can mix both APIs freely.
* High performance.
* Minimal dependencies for the basic library.
* Well-documented, stable API.
* Bindings in several programming languages.
* Shell (nbdsh) for command line and scripting.
Git: https://github.com/libguestfs/libnbd
Download: https://download.libguestfs.org/libnbd/1.4-stable/
Release notes:
https://libguestfs.org/libnbd-release-notes-1.4.1.html
Fedora: https://koji.fedoraproject.org/koji/packageinfo?packageID=28807
Debian: https://packages.debian.org/libnbd
*** Release notes for libnbd 1.4 ***
These are the release notes for libnbd stable release 1.4. This
describes the major changes since 1.2.
libnbd 1.4.0 was released on 25 August 2020.
Security
There were no security issues found in this release. If you find a
security issue, please read SECURITY in the source (online here:
https://github.com/libguestfs/libnbd/blob/master/SECURITY). To find
out about previous security issues in libnbd, see libnbd-security(3).
New APIs
nbd_set_opt_mode(3)
nbd_get_opt_mode(3)
nbd_aio_is_negotiating(3)
libnbd 1.4 adds a new “negotiating” state during NBD handshaking.
For backwards compatibility programs must request this before
starting the connection by calling nbd_set_opt_mode(3). You can
find out if the connection is in this state by calling
nbd_aio_is_negotiating(3).
For an in-depth description of how this extra state can be used to
negotiate server options, see "CONTROLLING NEGOTIATION" in
libnbd(3).
nbd_aio_opt_abort(3)
nbd_opt_abort(3)
During the negotiating state, abort the connection.
nbd_aio_opt_go(3)
nbd_opt_go(3)
During the negotiating state, complete the handshake.
nbd_aio_opt_info(3)
nbd_opt_info(3)
During the negotiating state, request full information about the
server export.
nbd_aio_opt_list(3)
nbd_opt_list(3)
During the negotiating state, request the list of exports that the
server provides.
nbd_get_block_size(3)
Return the minimum, preferred or maximum block size constraints for
requests sent to the server.
nbd_get_canonical_export_name(3)
Return the canonical export name that the server defaults to. This
information may only be available if you call nbd_set_full_info(3)
before connecting.
nbd_get_export_description(3)
Return the optional text description of the current export. This
information may only be available if you call nbd_set_full_info(3)
before connecting.
nbd_set_full_info(3)
nbd_get_full_info(3)
Enable extended information about exports from the server.
Thanks: Eric Blake for all of the new APIs.
New features
Bindings are now available in the Go programming language.
FreeBSD and OpenBSD are now fully supported platforms.
Bash tab completion is available for all of the command line tools.
Documentation
Verbatim text in man pages that wrapped over several lines is now
typeset correctly.
Links within the documentation have been enhanced, and are now checked
for correctness.
Tools
New nbdcopy(1) tool lets you copy between an NBD server and a local
file, or stream to and from an NBD server.
New nbdinfo(1) tool lets you print extended information about an NBD
server’s exports (Eric Blake).
Tests
Test sockets are created in /tmp (instead of the local directory).
This stops the test suite from failing if the local directory path is
longer than the Unix domain socket maximum path length.
Other improvements and bug fixes
Trace messages have been improved: long strings are truncated, strings
with non-printable characters are escaped, and lists of strings are
printed.
The generator was split from a large single script into several small
files. To build from git the OCaml bytecode compiler (ocamlc(1)) is
now required instead of the interpreter (ocaml(1)).
Long login names are supported in nbd_get_tls_username(3).
The handle name in nbdsh(1) is now set to "nbdsh" (instead of a
randomly generated name).
Compatibility with OCaml 4.10.0 and 4.11.0.
Python AIO buffer adds a new "is_zero" method allowing Python clients
to do sparsification when copying.
Compatibility with Python 3.9.
External C programs can now be compiled against libnbd’s build
directory using "../libnbd/run ./configure".
Honggfuzz can be used as another external fuzzing option.
Fix compilation with glibc 2.32 which deprecates "sys_errlist".
Many examples added or extended to demonstrate uses of the new APIs
(Eric Blake).
SEE ALSO
libnbd(3).
AUTHORS
Eric Blake
Richard W.M. Jones
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages. http://libguestfs.org
4 years, 1 month
[RFC nbdkit PATCH] protocol: Alter .list_exports, add .default_export
by Eric Blake
I'm about to add an 'exportname' filter, and in the process, I
noticed a few shortcomings in our API. Time to fix those before
the 1.22 release locks our API in stone. First, .list_exports
needs to know if it is pre- or post-TLS, as that may affect which
names are exported. Next, overloading .list_exports to do both
NBD_OPT_LIST and mapping "" to a canonical name is proving to be
awkward; the canonical mapping is only needed during an
NBD_INFO_NAME response to NBD_OPT_GO, and making .open try to
grab the entire .list_exports list just to use only the first
entry (even if the plugin optimized based on the bool to only
provide one entry) is awkward, compared to just having a
dedicated function. Finally, as long as we are going to support
NBD_INFO_NAME, we can also support NBD_INFO_DESCRIPTION; but
while we map "" to a canonical name prior to calling .open,
getting the description makes more sense after the connection
is established, alongside .get_size.
---
I obviously need to finish the code to go with this, but here's where
I would like to see the API before we finalize the 1.22 release.
docs/nbdkit-filter.pod | 41 +++++++++++++++++++----
docs/nbdkit-plugin.pod | 74 ++++++++++++++++++++++++++++++++++++------
2 files changed, 98 insertions(+), 17 deletions(-)
diff --git a/docs/nbdkit-filter.pod b/docs/nbdkit-filter.pod
index bf01db14..f15bdd96 100644
--- a/docs/nbdkit-filter.pod
+++ b/docs/nbdkit-filter.pod
@@ -339,12 +339,18 @@ an error message and return C<-1>.
=head2 C<.list_exports>
int (*list_exports) (nbdkit_next_list_exports *next, void *nxdata,
- int readonly, int default_only,
+ int readonly, int is_tls,
struct nbdkit_exports *exports);
This intercepts the plugin C<.list_exports> method and can be used to
filter which exports are advertised.
+The C<readonly> parameter matches what is passed to <.preconnect> and
+C<.open>, and may be changed by the filter when calling into the
+plugin. The C<is_tls> parameter informs the filter whether TLS
+negotiation has been completed by the client, but is not passed on to
+C<next> because it cannot be altered.
+
It is possible for filters to transform the exports list received back
from the layer below. Without error checking it would look like this:
@@ -355,8 +361,8 @@ from the layer below. Without error checking it would look like this:
struct nbdkit_export e;
char *name, *desc;
- exports2 = nbdkit_exports_new (default_only);
- next_list_exports (nxdata, readonly, default_only, exports);
+ exports2 = nbdkit_exports_new ();
+ next_list_exports (nxdata, readonly, exports);
for (i = 0; i < nbdkit_exports_count (exports2); ++i) {
e = nbdkit_get_export (exports2, i);
name = adjust (e.name);
@@ -376,11 +382,9 @@ an error message and return C<-1>.
Two functions are provided to filters only for allocating and freeing
the list:
- struct nbdkit_exports *nbdkit_exports_new (int default_only);
+ struct nbdkit_exports *nbdkit_exports_new (void);
-Allocates and returns a new, empty exports list. The C<default_only>
-parameter should match whether the list is intended to grab the
-canonical name of the default export, or all exports.
+Allocates and returns a new, empty exports list.
On error this function can return C<NULL>. In this case it calls
C<nbdkit_error> as required. C<errno> will be set to a suitable
@@ -408,6 +412,20 @@ Returns the number of exports in the list.
Returns a copy of the C<i>'th export.
+=head2 C<.default_export>
+
+ const char *default_export (nbdkit_next_default_export *next, void *nxdata,
+ int readonly, int is_tls)
+
+This intercepts the plugin C<.default_export> method and can be used to
+alter the canonical export name used in place of the default C<"">.
+
+The C<readonly> parameter matches what is passed to <.preconnect> and
+C<.open>, and may be changed by the filter when calling into the
+plugin. The C<is_tls> parameter informs the filter whether TLS
+negotiation has been completed by the client, but is not passed on to
+C<next> because it cannot be altered.
+
=head2 C<.open>
void * (*open) (nbdkit_next_open *next, void *nxdata,
@@ -527,6 +545,15 @@ This function is only called once per connection and cached by nbdkit.
Similarly, repeated calls to C<next_ops-E<gt>get_size> will return a
cached value.
+=head2 C<.export_description>
+
+ const char *export_description (struct nbdkit_next_ops *next_ops,
+ void *nxdata, void *handle);
+
+This intercepts the plugin C<.export_description> method and can be
+used to read or modify the export description that the NBD client
+will see.
+
=head2 C<.can_write>
=head2 C<.can_flush>
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 5c641e83..ecb6bba8 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -245,6 +245,12 @@ Early in option negotiation the client may try to list the exports
served by the plugin, and plugins can optionally implement this
callback to answer the client. See L</EXPORT NAME> below.
+=item C<.default_export>
+
+During option negotiation, if the client requests the default export
+name (C<"">), this optional callback provides a canonical name to
+use in its place prior to calling C<.open>.
+
=item C<.open>
A new client has connected and finished the NBD handshake. TLS
@@ -664,15 +670,16 @@ error message and return C<-1>.
=head2 C<.list_exports>
- int list_exports (int readonly, int default_only,
+ int list_exports (int readonly, int is_tls,
struct nbdkit_exports *exports);
This optional callback is called if the client tries to list the
exports served by the plugin (using C<NBD_OPT_LIST>). If the plugin
-does not supply this callback then a single export called C<""> is
-returned. The NBD protocol defines C<""> as the default export, so
-this is suitable for plugins which ignore the export name and always
-serve the same content. See also L</EXPORT NAME> below.
+does not supply this callback then the reply is determined by the
+result of C<.default_export>, which in turn defaults to advertising
+the name C<"">. The NBD protocol defines C<""> as the default export,
+so this default is suitable for plugins which ignore the export name
+and always serve the same content. See also L</EXPORT NAME> below.
The C<readonly> flag informs the plugin that the server was started
with the I<-r> flag on the command line, which is the same value
@@ -681,11 +688,11 @@ not yet have a way to let the client advertise an intent to be
read-only even when the server allows writes, so this parameter may
not be as useful as it appears.
-If the C<default_only> flag is set then the client is querying for the
-name of the default export, and the plugin may optimize by adding only
-a single export to the returned list (the default export name, usually
-C<"">). The plugin can ignore this flag and return all exports if it
-wants.
+The C<is_tls> flag informs the plugin whether this listing was
+requested after the client has completed TLS negotiation. When
+running the server in a mode that permits but not requires TLS,
+be careful that any exports listed when C<is_tls> is C<false> do
+not leak unintended information.
The C<exports> parameter is an opaque object for collecting the list
of exports. Call C<nbdkit_add_export> to add a single export to the
@@ -709,6 +716,37 @@ Returning C<0> will send the list of exports back to the client. If
there is an error, C<.list_exports> should call C<nbdkit_error> with
an error message and return C<-1>.
+=head2 C<.default_export>
+
+ const char *default_export (int readonly, int is_tls);
+
+This optional callback is called if the client tries to connect to
+the default export C<"">. If the plugin does not supply this callback,
+the connection continues with the empty name; if the plugin returns
+a string, nbdkit returns that name to clients that support it (see
+the C<NBD_INFO_NAME> response to C<NBD_OPT_GO>), and behaves as if
+the client had passed that string instead of an empty name. Similarly,
+if the plugin does not supply a C<.list_exports> callback, the result
+of this callback determines what export name to advertise to a client
+requesting an export list.
+
+The C<readonly> flag informs the plugin that the server was started
+with the I<-r> flag on the command line, which is the same value
+passed to C<.preconnect> and C<.open>. However, the NBD protocol does
+not yet have a way to let the client advertise an intent to be
+read-only even when the server allows writes, so this parameter may
+not be as useful as it appears.
+
+The C<is_tls> flag informs the plugin whether the canonical name for
+the default export is being requested after the client has completed
+TLS negotiation. When running the server in a mode that permits but
+not requires TLS, be careful that a default export name does not leak
+unintended information.
+
+If the plugin returns C<NULL>, the client is not permitted to connect
+to the default export. However, this is not an error in the protocol,
+so it is not necessary to call C<nbdkit_error>.
+
=head2 C<.open>
void *open (int readonly);
@@ -769,6 +807,22 @@ to get the size (in bytes) of the block device being exported.
The returned size must be E<ge> 0. If there is an error, C<.get_size>
should call C<nbdkit_error> with an error message and return C<-1>.
+=head2 C<.export_description>
+
+ const char *export_description (void *handle);
+
+This is called during the option negotiation phase only if the
+client specifically requested an export description (see the
+C<NBD_INFO_DESCRIPTION> response to C<NBD_OPT_GO>). Any
+description provided must be human-readable UTF-8, no longer
+than 4096 bytes. Ideally, this description should match any
+description set during C<.list_exports>, but that is not
+enforced.
+
+If the plugin returns C<NULL>, or if this callback is omitted, no
+description is offered to the client. As this is not an error in the
+protocol, it is not necessary to call C<nbdkit_error>.
+
=head2 C<.can_write>
int can_write (void *handle);
--
2.28.0
4 years, 1 month