[Libguestfs] [libnbd PATCH v2 02/13] info: Improve info without --list

Eric Blake
Fri, 14 Aug 2020 22:00:21 -0000

Make use of the new nbd_get_export_description to list a description
when connecting to a single export.

At present, only qemu-nbd offers the needed information; it would
require a patch to nbdkit to do likewise (although such a patch is not
difficult, given that we recently added .list_exports).
---
 generator/API.ml         |  3 +++
 examples/server-flags.c  | 23 +++++++++++++++++
 info/Makefile.am         |  1 +
 info/info-description.sh | 56 ++++++++++++++++++++++++++++++++++++++++
 info/nbdinfo.c           | 16 +++++++++---
 5 files changed, 95 insertions(+), 4 deletions(-)
 create mode 100755 info/info-description.sh

diff --git a/generator/API.ml b/generator/API.ml
index eff0ac4..0c8ef30 100644
--- a/generator/API.ml
+++ b/generator/API.ml
@@ -322,6 +322,7 @@ Note that even when full info is requested, the server is
not
 obligated to reply with all information that libnbd requested.
 Similarly, libnbd will ignore any optional server information that
 libnbd has not yet been taught to recognize.";
+    example = Some "examples/server-flags.c";
     see_also = [Link "get_full_info"; Link
"get_canonical_export_name";
                 Link "get_export_description"];
   };
@@ -352,6 +353,7 @@ C<\"\">).

 Some servers are unlikely to report a canonical name unless the
 client specifically hinted about wanting it, via
L<nbd_set_full_info(3)>.";
+    example = Some "examples/server-flags.c";
     see_also = [Link "set_full_info"; Link
"get_export_name"];
   };

@@ -368,6 +370,7 @@ the server.
 Some servers are unlikely to report description unless the
 client specifically hinted about wanting it, via L<nbd_set_full_info(3)>.
 For L<qemu-nbd(8)>, a description is set with I<-D>.";
+    example = Some "examples/server-flags.c";
     see_also = [Link "set_full_info"];
   };

diff --git a/examples/server-flags.c b/examples/server-flags.c
index d06f02f..d156ace 100644
--- a/examples/server-flags.c
+++ b/examples/server-flags.c
@@ -16,6 +16,7 @@ int
 main (int argc, char *argv[])
 {
   struct nbd_handle *nbd;
+  char *str;
   int flag;

   if (argc != 2) {
@@ -30,6 +31,14 @@ main (int argc, char *argv[])
     exit (EXIT_FAILURE);
   }

+  /* Request full information. */
+#if LIBNBD_HAVE_NBD_SET_FULL_INFO /* Added in 1.4 */
+  if (nbd_set_full_info (nbd, true) == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+#endif
+
   /* Connect to the NBD server over a
    * Unix domain socket.
    */
@@ -38,6 +47,20 @@ main (int argc, char *argv[])
     exit (EXIT_FAILURE);
   }

+  /* See if the server provided extra details,
+   * using functions added in 1.4
+   */
+#if LIBNBD_HAVE_NBD_GET_EXPORT_DESCRIPTION
+  str = nbd_get_canonical_export_name (nbd);
+  if (str)
+    printf ("canonical_name = %s\n", str);
+  free (str);
+  str = nbd_get_export_description (nbd);
+  if (str)
+    printf ("description = %s\n", str);
+  free (str);
+#endif
+
   /* Read and print the flags. */
 #define PRINT_FLAG(flag_fn)                     \
   flag = flag_fn (nbd);                         \
diff --git a/info/Makefile.am b/info/Makefile.am
index 22c0c28..05b8137 100644
--- a/info/Makefile.am
+++ b/info/Makefile.am
@@ -66,6 +66,7 @@ TESTS += \
 	info-oldstyle.sh \
 	info-size.sh \
 	info-text.sh \
+	info-description.sh \
 	$(NULL)

 check-valgrind:
diff --git a/info/info-description.sh b/info/info-description.sh
new file mode 100755
index 0000000..d367a25
--- /dev/null
+++ b/info/info-description.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+# nbd client library in userspace
+# Copyright (C) 2020 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
+
+# XXX Use nbdkit once it supports NBD_INFO_DESCRIPTION
+requires qemu-nbd --version
+requires truncate --version
+
+img=info-description.img
+out=info-description.out
+pid=info-description.pid
+sock=`mktemp -u`
+cleanup_fn rm -f $img $out $pid $sock
+rm -f $img $out $pid $sock
+
+truncate -s 1M $img
+qemu-nbd -f raw -t --socket=$sock --pid-file=$pid -x "hello" -D
"world" $img &
+cleanup_fn kill $!
+
+# Wait for qemu-nbd to start up.
+for i in {1..60}; do
+    if test -f $pid; then
+        break
+    fi
+    sleep 1
+done
+if ! test -f $pid; then
+    echo "$0: qemu-nbd did not start up"
+    exit 1
+fi
+
+$VG nbdinfo "nbd+unix:///hello?socket=$sock" > $out
+cat $out
+
+grep 'export="hello":' $out
+grep 'description: world' $out
+grep 'export-size: 1048576' $out
diff --git a/info/nbdinfo.c b/info/nbdinfo.c
index 454e5c5..b54dfd4 100644
--- a/info/nbdinfo.c
+++ b/info/nbdinfo.c
@@ -99,6 +99,7 @@ main (int argc, char *argv[])
   int64_t size;
   const char *protocol;
   int tls_negotiated;
+  char *desc;

   for (;;) {
     c = getopt_long (argc, argv, short_options, long_options, NULL);
@@ -191,6 +192,8 @@ main (int argc, char *argv[])
    */
   if (list_all)
     nbd_set_list_exports (nbd, true);
+  else if (!size_only)
+    nbd_set_full_info (nbd, true);

   if (nbd_connect_uri (nbd, argv[optind]) == -1) {
     if (!list_all || nbd_get_errno () == ENOTSUP) {
@@ -244,9 +247,11 @@ main (int argc, char *argv[])
         printf ("\"TLS\": %s,\n", tls_negotiated ?
"true" : "false");
     }

-    if (!list_all)
-      /* XXX We would need libnbd to request NBD_INFO_DESCRIPTION */
-      list_one_export (nbd, NULL, true, true);
+    if (!list_all) {
+      desc = nbd_get_export_description (nbd);
+      list_one_export (nbd, desc, true, true);
+      free (desc);
+    }
     else
       list_all_exports (nbd, argv[optind]);

@@ -277,7 +282,10 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
     exit (EXIT_FAILURE);
   }

-  export_name = nbd_get_export_name (nbd);
+  /* Prefer the server's version of the name, if available */
+  export_name = nbd_get_canonical_export_name (nbd);
+  if (export_name == NULL)
+    export_name = nbd_get_export_name (nbd);
   if (export_name == NULL) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
--
2.28.0