Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 0/5] lib: New API nbd_get_uri
Slightly more evolved version of this patch series from yesterday: https://listman.redhat.com/archives/libguestfs/2021-April/msg00015.html In v2: - I've split up the patch some more - made it possible to reverse AF_INET/AF_INET6 from a call to nbd_aio_connect (which takes a raw sockaddr) - catch the Unix domain socket abstract namespace case (not supported) - added more testing Rich.
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 1/5] generator: Avoid over-long lines in POD.
If there are too many states in the permitted_states list then it would cause over-long lines in POD which podwrapper objected to. --- generator/C.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generator/C.ml b/generator/C.ml index fe8eafc..3e9975f 100644 --- a/generator/C.ml +++ b/generator/C.ml @@ -416,10 +416,10 @@ let generate_lib_unlocked_h () pr "\n"; pr "#endif /* LIBNBD_UNLOCKED_H */\n" -let permitted_state_text permitted_states +let permitted_state_text ?(fold=false) permitted_states assert (permitted_states <> []); - String.concat - ", or " + let sep = if fold then ", or\n" else ", or " in + String.concat sep (List.map ( function | Created -> "newly created" @@ -913,7 +913,7 @@ let generate_docs_nbd_pod name { args; optargs; ret; pr "=head1 HANDLE STATE\n"; pr "\n"; pr "The handle must be\n"; - pr "%s,\n" (permitted_state_text permitted_states); + pr "%s,\n" (permitted_state_text ~fold:true permitted_states); pr "otherwise this call will return an error.\n"; pr "\n" ); -- 2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 2/5] generator: Permit "see also" links to nbd_get_error and nbd_get_errno.
--- generator/API.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generator/API.ml b/generator/API.ml index dd66fdb..6300b1c 100644 --- a/generator/API.ml +++ b/generator/API.ml @@ -3045,7 +3045,8 @@ let pod_of_link = function let verify_link let pages = List.map fst handle_calls in function - | Link "create" | Link "close" -> () + | Link "create" | Link "close" + | Link "get_error" | Link "get_errno" -> () | Link page -> if not (List.mem page pages) then failwithf "verify_link: page nbd_%s does not exist" page -- 2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 3/5] tests: Add a new test for nbd_aio_connect.
This was not tested before. --- .gitignore | 1 + tests/Makefile.am | 7 +++ tests/aio-connect.c | 106 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/.gitignore b/.gitignore index ffe6261..29ff60b 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,7 @@ Makefile.in /sh/nbdsh.1 /stamp-h1 /test-driver +/tests/aio-connect /tests/aio-parallel /tests/aio-parallel-load /tests/aio-parallel-load-tls diff --git a/tests/Makefile.am b/tests/Makefile.am index 1fad236..396fd7e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -179,6 +179,7 @@ check_PROGRAMS += \ opt-list-meta \ connect-unix \ connect-tcp \ + aio-connect \ aio-parallel \ aio-parallel-load \ synch-parallel \ @@ -219,6 +220,7 @@ TESTS += \ opt-list-meta \ connect-unix \ connect-tcp \ + aio-connect \ aio-parallel.sh \ aio-parallel-load.sh \ synch-parallel.sh \ @@ -435,6 +437,11 @@ connect_tcp_CPPFLAGS = -I$(top_srcdir)/include connect_tcp_CFLAGS = $(WARNINGS_CFLAGS) connect_tcp_LDADD = $(top_builddir)/lib/libnbd.la +aio_connect_SOURCES = aio-connect.c +aio_connect_CPPFLAGS = -I$(top_srcdir)/include +aio_connect_CFLAGS = $(WARNINGS_CFLAGS) +aio_connect_LDADD = $(top_builddir)/lib/libnbd.la + aio_parallel_SOURCES = aio-parallel.c aio_parallel_CPPFLAGS = \ -I$(top_srcdir)/include \ diff --git a/tests/aio-connect.c b/tests/aio-connect.c new file mode 100644 index 0000000..50e9055 --- /dev/null +++ b/tests/aio-connect.c @@ -0,0 +1,106 @@ +/* NBD client library in userspace + * Copyright (C) 2013-2021 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Test connecting to an IPv4 TCP port using nbd_aio_connect. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <libnbd.h> + +#define PIDFILE "aio-connect.pid" + +int +main (int argc, char *argv[]) +{ + struct nbd_handle *nbd; + int port; + char port_str[16]; + pid_t pid; + size_t i; + struct sockaddr_in addr; + + unlink (PIDFILE); + + /* Pick a port at random, hope it's free. */ + srand (time (NULL) + getpid ()); + port = 32768 + (rand () & 32767); + + snprintf (port_str, sizeof port_str, "%d", port); + + pid = fork (); + if (pid == -1) { + perror ("fork"); + exit (EXIT_FAILURE); + } + if (pid == 0) { + execlp ("nbdkit", + "nbdkit", "-f", "-p", port_str, "-P", PIDFILE, + "--exit-with-parent", "null", NULL); + perror ("nbdkit"); + _exit (EXIT_FAILURE); + } + + /* Wait for nbdkit to start listening. */ + for (i = 0; i < 60; ++i) { + if (access (PIDFILE, F_OK) == 0) + break; + sleep (1); + } + unlink (PIDFILE); + + nbd = nbd_create (); + if (nbd == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + addr.sin_port = htons (port); + + if (nbd_aio_connect (nbd, (struct sockaddr *) &addr, sizeof addr) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + /* Wait until we have connected. */ + while (!nbd_aio_is_ready (nbd)) { + if (nbd_poll (nbd, -1) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + } + + if (nbd_shutdown (nbd, 0) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + nbd_close (nbd); + exit (EXIT_SUCCESS); +} -- 2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 4/5] lib: New API nbd_get_uri to get an NBD URI for a connection.
This will make a best-effort attempt to construct an NBD URI for connecting back to the current server. In many cases this is not really possible (eg. if we were connected with nbd_connect_socket), and it's not guaranteed to be correct. --- generator/API.ml | 28 +++++++- lib/uri.c | 167 +++++++++++++++++++++++++++++++++++++++++++ tests/aio-connect.c | 19 +++++ tests/connect-tcp.c | 20 ++++++ tests/connect-unix.c | 20 ++++++ tests/connect-uri.c | 17 +++++ 6 files changed, 269 insertions(+), 2 deletions(-) diff --git a/generator/API.ml b/generator/API.ml index 6300b1c..2f1baa8 100644 --- a/generator/API.ml +++ b/generator/API.ml @@ -1383,7 +1383,7 @@ compiled with gnutls; you can test whether this is the case with L<nbd_supports_tls(3)>."; see_also = [URLLink "https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md"; Link "set_export_name"; Link "set_tls"; - Link "set_opt_mode"]; + Link "set_opt_mode"; Link "get_uri"]; }; "connect_unix", { @@ -2875,7 +2875,30 @@ to support TLS encryption, or false if not."; longdesc = "\ Returns true if libnbd was compiled with libxml2 which is required to support NBD URIs, or false if not."; - see_also = [Link "connect_uri"; Link "aio_connect_uri"]; + see_also = [Link "connect_uri"; Link "aio_connect_uri"; + Link "get_uri"]; + }; + + "get_uri", { + default_call with + args = []; ret = RString; + permitted_states = [ Connecting; Negotiating; Connected; Closed; Dead ]; + shortdesc = "construct an NBD URI for a connection"; + longdesc = "\ +This makes a best effort attempt to construct an NBD URI which +could be used to connect to this NBD server (eg. using +L<nbd_connect_uri(3)>). + +The URI returned is not guaranteed to work, and in some cases +(eg. if connected with L<nbd_connect_socket(3)>) it is not possible +at all. Even if a URI is returned it may not be optimal. + +On error, L<nbd_get_errno(3)> will be set to C<ENOTSUP> if the +library was compiled without support for URIs. In other error +cases, L<nbd_get_errno(3)> and L<nbd_get_error(3)> should contain +information about why constructing a URI was not possible."; + see_also = [Link "connect_uri"; Link "aio_connect_uri"; + Link "supports_uri"]; }; ] @@ -3009,6 +3032,7 @@ let first_version = [ (* Added in 1.7.x development cycle, will be stable and supported in 1.8. *) "set_private_data", (1, 8); "get_private_data", (1, 8); + "get_uri", (1, 8); (* These calls are proposed for a future version of libnbd, but * have not been added to any released version so far. diff --git a/lib/uri.c b/lib/uri.c index 9f5a290..06eda19 100644 --- a/lib/uri.c +++ b/lib/uri.c @@ -25,6 +25,14 @@ #include <string.h> #include <errno.h> #include <assert.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netdb.h> + +#ifdef HAVE_LINUX_VM_SOCKETS_H +#include <linux/vm_sockets.h> +#endif #include "internal.h" #include "vector.h" @@ -335,6 +343,158 @@ cleanup: return ret; } +/* This is best effort. If we didn't save enough information when + * connecting then return NULL but try to set errno and the error + * string to something useful. + */ + +static int append_query_params (char **query_params, + const char *key, const char *value); + +char * +nbd_unlocked_get_uri (struct nbd_handle *h) +{ + xmlURI uri = { 0 }; + bool using_tls; + char *server = NULL; + char *query_params = NULL; + char *path = NULL; + char *ret = NULL; + + if (h->tls == 2) /* TLS == require */ + using_tls = true; + else if (h->tls_negotiated) + using_tls = true; + else + using_tls = false; + + /* Set scheme, server or socket. */ + if (h->hostname && h->port) { + uri.scheme = using_tls ? "nbds" : "nbd"; + if (asprintf (&server, "%s:%s", h->hostname, h->port) == -1) { + set_error (errno, "asprintf"); + goto out; + } + uri.server = server; + } + + else if (h->connaddrlen > 0) { + switch (h->connaddr.ss_family) { + case AF_INET: + case AF_INET6: { + int err; + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; + + uri.scheme = using_tls ? "nbds" : "nbd"; + err = getnameinfo ((struct sockaddr *) &h->connaddr, h->connaddrlen, + host, sizeof host, serv, sizeof serv, NI_NUMERICHOST); + if (err != 0) { + set_error (0, "getnameinfo: %s", gai_strerror (err)); + goto out; + } + if (asprintf (&server, "%s:%s", host, serv) == -1) { + set_error (errno, "asprintf"); + goto out; + } + uri.server = server; + break; + } + + case AF_UNIX: { + struct sockaddr_un *sun = (struct sockaddr_un *) &h->connaddr; + + if (sun->sun_path[0] == '\0') { + /* Unix domain sockets in the abstract namespace are in theory + * supported in NBD URIs, but libxml2 cannot handle them so + * libnbd cannot use them here or in nbd_connect_uri. + */ + set_error (EPROTONOSUPPORT, "Unix domain sockets in the " + "abstract namespace are not yet supported"); + goto out; + } + + uri.scheme = using_tls ? "nbds+unix" : "nbd+unix"; + if (append_query_params (&query_params, "socket", sun->sun_path) == -1) + goto out; + /* You have to set this otherwise xmlSaveUri generates bogus + * URIs "nbd+unix:/?socket=..." + */ + uri.server = ""; + break; + } + +#ifdef AF_VSOCK + case AF_VSOCK: { + struct sockaddr_vm *svm = (struct sockaddr_vm *) &h->connaddr; + + uri.scheme = using_tls ? "nbds+vsock" : "nbd+vsock"; + if (asprintf (&server, "%u:%u", svm->svm_cid, svm->svm_port) == -1) { + set_error (errno, "asprintf"); + goto out; + } + uri.server = server; + break; + } +#endif + + default: + set_error (EAFNOSUPPORT, + "address family %d not supported", h->connaddr.ss_family); + goto out; + } + } + + else { + set_error (EINVAL, "cannot construct a URI for this connection type"); + goto out; + } + + /* Set other fields. */ + if (h->tls_username) + uri.user = h->tls_username; + if (h->export_name) { + if (asprintf (&path, "/%s", h->export_name) == -1) { + set_error (errno, "asprintf"); + goto out; + } + uri.path = path; + } + if (h->tls_psk_file) { + if (append_query_params (&query_params, + "tls-psk-file", h->tls_psk_file) == -1) + goto out; + } + + uri.query_raw = query_params; + + /* Construct the final URI and return it. */ + ret = (char *) xmlSaveUri (&uri); + if (ret == NULL) + set_error (errno, "xmlSaveUri failed"); + out: + free (server); + free (query_params); + free (path); + return ret; +} + +static int +append_query_params (char **query_params, const char *key, const char *value) +{ + char *old_query_params = *query_params; + + if (asprintf (query_params, "%s%s%s=%s", + old_query_params ? : "", + old_query_params ? "&" : "", + key, value) == -1) { + set_error (errno, "asprintf"); + return -1; + } + free (old_query_params); + return 0; +} + #else /* !HAVE_LIBXML2 */ #define NOT_SUPPORTED_ERROR \ @@ -354,4 +514,11 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char *raw_uri) return -1; } +char * +nbd_unlocked_get_uri (struct nbd_handle *h) +{ + set_error (ENOTSUP, NOT_SUPPORTED_ERROR); + return NULL; +} + #endif /* !HAVE_LIBXML2 */ diff --git a/tests/aio-connect.c b/tests/aio-connect.c index 50e9055..0584005 100644 --- a/tests/aio-connect.c +++ b/tests/aio-connect.c @@ -43,6 +43,7 @@ main (int argc, char *argv[]) pid_t pid; size_t i; struct sockaddr_in addr; + char *actual_uri, *expected_uri; unlink (PIDFILE); @@ -96,6 +97,24 @@ main (int argc, char *argv[]) } } + /* libnbd should be able to construct a URI for this connection. */ + if (asprintf (&expected_uri, "nbd://127.0.0.1:%s/", port_str) == -1) { + perror ("asprintf"); + exit (EXIT_FAILURE); + } + actual_uri = nbd_get_uri (nbd); + if (actual_uri == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (strcmp (actual_uri, expected_uri) != 0) { + fprintf (stderr, "%s: actual URI %s != expected URI %s\n", + argv[0], actual_uri, expected_uri); + exit (EXIT_FAILURE); + } + free (actual_uri); + free (expected_uri); + if (nbd_shutdown (nbd, 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/tests/connect-tcp.c b/tests/connect-tcp.c index d7a36e4..e96b1ec 100644 --- a/tests/connect-tcp.c +++ b/tests/connect-tcp.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <fcntl.h> #include <unistd.h> #include <time.h> @@ -38,6 +39,7 @@ main (int argc, char *argv[]) char port_str[16]; pid_t pid; size_t i; + char *actual_uri, *expected_uri; unlink (PIDFILE); @@ -79,6 +81,24 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* libnbd should be able to construct a URI for this connection. */ + if (asprintf (&expected_uri, "nbd://localhost:%s/", port_str) == -1) { + perror ("asprintf"); + exit (EXIT_FAILURE); + } + actual_uri = nbd_get_uri (nbd); + if (actual_uri == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (strcmp (actual_uri, expected_uri) != 0) { + fprintf (stderr, "%s: actual URI %s != expected URI %s\n", + argv[0], actual_uri, expected_uri); + exit (EXIT_FAILURE); + } + free (actual_uri); + free (expected_uri); + if (nbd_shutdown (nbd, 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/tests/connect-unix.c b/tests/connect-unix.c index 8c18166..0000b98 100644 --- a/tests/connect-unix.c +++ b/tests/connect-unix.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <fcntl.h> #include <unistd.h> @@ -36,6 +37,7 @@ main (int argc, char *argv[]) struct nbd_handle *nbd; pid_t pid; size_t i; + char *actual_uri, *expected_uri; if (mkstemp (socket) == -1) { perror (socket); @@ -77,6 +79,24 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* libnbd should be able to construct a URI for this connection. */ + if (asprintf (&expected_uri, "nbd+unix:///?socket=%s", socket) == -1) { + perror ("asprintf"); + exit (EXIT_FAILURE); + } + actual_uri = nbd_get_uri (nbd); + if (actual_uri == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (strcmp (actual_uri, expected_uri) != 0) { + fprintf (stderr, "%s: actual URI %s != expected URI %s\n", + argv[0], actual_uri, expected_uri); + exit (EXIT_FAILURE); + } + free (actual_uri); + free (expected_uri); + if (nbd_shutdown (nbd, 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/tests/connect-uri.c b/tests/connect-uri.c index 6e7d168..9093247 100644 --- a/tests/connect-uri.c +++ b/tests/connect-uri.c @@ -35,6 +35,7 @@ main (int argc, char *argv[]) struct nbd_handle *nbd; pid_t pid; size_t i; + char *get_uri; #ifdef SOCKET unlink (SOCKET); @@ -89,6 +90,22 @@ main (int argc, char *argv[]) } } + /* Usually the URI returned by nbd_get_uri should be the same as the + * one passed to nbd_connect_uri, or at least it will be in our test + * cases. + */ + get_uri = nbd_get_uri (nbd); + if (get_uri == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (strcmp (URI, get_uri) != 0) { + fprintf (stderr, "%s: connect URI %s != get URI %s\n", + argv[0], URI, get_uri); + exit (EXIT_FAILURE); + } + free (get_uri); + if (nbd_shutdown (nbd, 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); -- 2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 5/5] info: Print the URI in the output, if possible.
--- info/Makefile.am | 1 + info/info-list-uris.sh | 46 ++++++++++++++++++++++++++++++++++++++++++ info/info-text.sh | 1 + info/nbdinfo.c | 12 +++++++++++ info/nbdinfo.pod | 2 ++ 5 files changed, 62 insertions(+) diff --git a/info/Makefile.am b/info/Makefile.am index 1f0a6a3..c19c394 100644 --- a/info/Makefile.am +++ b/info/Makefile.am @@ -22,6 +22,7 @@ info_sh_files = \ info-list-json.sh \ info-list-qemu.sh \ info-list-json-qemu.sh \ + info-list-uris.sh \ info-json.sh \ info-oldstyle.sh \ info-null.sh \ diff --git a/info/info-list-uris.sh b/info/info-list-uris.sh new file mode 100755 index 0000000..28693aa --- /dev/null +++ b/info/info-list-uris.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# nbd client library in userspace +# Copyright (C) 2020-2021 Red Hat Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +. ../tests/functions.sh + +set -e +set -x + +requires nbdkit --version +requires nbdkit file --version + +# This test requires nbdkit >= 1.22. +minor=$( nbdkit --dump-config | grep ^version_minor | cut -d= -f2 ) +requires test $minor -gt 22 + +out=info-list-uris.out +cleanup_fn rm -f $out + +# nbdinfo --list is not very stable in the particular case where +# exports come and go while it is running. This happens if we set the +# directory to be the current directory since other tests create +# temporary files here. So point this to a more stable directory. + +nbdkit -U - file dir=$srcdir/../examples \ + --run '$VG nbdinfo --list "$uri"' > $out +cat $out + +# We expect to see URIs corresponding to some well-known files +# (ie. exports) in the examples directory. +grep "uri: nbd+unix:///LICENSE-FOR-EXAMPLES?socket=" $out +grep "uri: nbd+unix:///get-size.c?socket=" $out diff --git a/info/info-text.sh b/info/info-text.sh index bf98405..5585a48 100755 --- a/info/info-text.sh +++ b/info/info-text.sh @@ -31,4 +31,5 @@ nbdkit -U - memory size=1M \ --run '$VG nbdinfo "nbd+unix:///?socket=$unixsocket"' > $out cat $out grep "export-size: $((1024*1024))" $out +grep "uri: nbd+unix:///?socket=" $out sed -n '/contexts:/ { N; p; q }; $ q1' $out diff --git a/info/nbdinfo.c b/info/nbdinfo.c index 3dfc463..b35e682 100644 --- a/info/nbdinfo.c +++ b/info/nbdinfo.c @@ -407,6 +407,7 @@ list_one_export (struct nbd_handle *nbd, const char *desc, char *export_name = NULL; char *export_desc = NULL; char *content = NULL; + char *uri = NULL; int is_rotational, is_read_only; int can_cache, can_df, can_fast_zero, can_flush, can_fua, can_multi_conn, can_trim, can_zero; @@ -433,6 +434,8 @@ list_one_export (struct nbd_handle *nbd, const char *desc, exit (EXIT_FAILURE); } + uri = nbd_get_uri (nbd); + /* Prefer the server's version of the name, if available */ export_name = nbd_get_canonical_export_name (nbd); if (export_name == NULL) @@ -475,6 +478,8 @@ list_one_export (struct nbd_handle *nbd, const char *desc, fprintf (fp, "\texport-size: %" PRIi64 "\n", size); if (content) fprintf (fp, "\tcontent: %s\n", content); + if (uri) + fprintf (fp, "\turi: %s\n", uri); if (show_context) { fprintf (fp, "\tcontexts:\n"); for (i = 0; i < contexts.size; ++i) @@ -533,6 +538,12 @@ list_one_export (struct nbd_handle *nbd, const char *desc, fprintf (fp, ",\n"); } + if (uri) { + fprintf (fp, "\t\"uri\": "); + print_json_string (uri); + fprintf (fp, ",\n"); + } + if (show_context) { fprintf (fp, "\t\"contexts\": [\n"); for (i = 0; i < contexts.size; ++i) { @@ -600,6 +611,7 @@ list_one_export (struct nbd_handle *nbd, const char *desc, free (content); free (export_name); free (export_desc); + free (uri); return true; } diff --git a/info/nbdinfo.pod b/info/nbdinfo.pod index 99c74a2..5bc624c 100644 --- a/info/nbdinfo.pod +++ b/info/nbdinfo.pod @@ -23,6 +23,7 @@ L<https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md>): export="": export-size: 1048576 content: data + uri: nbd://localhost:10809/ is_rotational: false is_read_only: false can_cache: true @@ -63,6 +64,7 @@ the I<--json> parameter: { "export-name": "", "content": "DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x3ff,254,63), end-CHS (0x3ff,254,63), startsector 2048, 4148704 sectors", + "uri": "nbd://localhost:10809/", "is_rotational": false, "is_read_only": true, "can_cache": true, -- 2.29.0.rc2