[Libguestfs] guestfish Remote Images IPv6 Support
Richard W.M. Jones
rjones at redhat.com
Mon Apr 1 15:45:10 UTC 2019
On Mon, Apr 01, 2019 at 09:45:56AM -0500, Jonathan Wright wrote:
> I believe the bug lies in libguestfs.
>
> Taking out the commands being sent to QEMU and using qemu-img info I
> can recreate the error:
>
> # qemu-img info "rbd:images/CentOS-7-x86_64-GenericCloud-1901:mon_host=[fd00::cefc:1]\:6789:auth_supported=none"
> qemu-img: Could not open 'rbd:images/CentOS-7-x86_64-GenericCloud-1901:mon_host=[fd00::cefc:1]\:6789:auth_supported=none':
> invalid conf option :cefc:1]:6789:auth_supported: No such file or
> directory
>
> When escaping the : in the v6 address (just like is done with the
> port's : ) the command works as expected.
Ah I see. Can you try the small patch attached?
Rich.
--
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
-------------- next part --------------
>From a23969a4505a7cfb8d741b81e70ab23a868862c7 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Mon, 1 Apr 2019 16:36:15 +0100
Subject: [PATCH] lib: qemu: rbd: Properly escape IPv6 addresses.
Each ':' character in the address must be escaped from qemu.
Thanks: Jonathan Wright
---
common/utils/guestfs-utils.h | 1 +
common/utils/utils.c | 47 ++++++++++++++++++++++++++++++++++++
lib/qemu.c | 37 +++++++++-------------------
3 files changed, 60 insertions(+), 25 deletions(-)
diff --git a/common/utils/guestfs-utils.h b/common/utils/guestfs-utils.h
index 1459a4c3c..52aeca012 100644
--- a/common/utils/guestfs-utils.h
+++ b/common/utils/guestfs-utils.h
@@ -47,6 +47,7 @@ extern char *guestfs_int_concat_strings (char *const *);
extern char **guestfs_int_copy_string_list (char *const *);
extern char *guestfs_int_join_strings (const char *sep, char *const *);
extern char **guestfs_int_split_string (char sep, const char *);
+extern char *guestfs_int_replace_string (const char *str, const char *s1, const char *s2);
extern char *guestfs_int_exit_status_to_string (int status, const char *cmd_name, char *buffer, size_t buflen);
extern int guestfs_int_random_string (char *ret, size_t len);
extern char *guestfs_int_drive_name (size_t index, char *ret);
diff --git a/common/utils/utils.c b/common/utils/utils.c
index 48e7ed4d1..18725f693 100644
--- a/common/utils/utils.c
+++ b/common/utils/utils.c
@@ -214,6 +214,53 @@ guestfs_int_split_string (char sep, const char *str)
return ret;
}
+/**
+ * Replace every instance of C<s1> appearing in C<str> with C<s2>. A
+ * newly allocated string is returned which must be freed by the
+ * caller. If allocation fails this can return C<NULL>.
+ *
+ * For example:
+ *
+ * replace_string ("abcabb", "ab", "a");
+ *
+ * would return C<"acab">.
+ */
+char *
+guestfs_int_replace_string (const char *str, const char *s1, const char *s2)
+{
+ const size_t len = strlen (str), s1len = strlen (s1), s2len = strlen (s2);
+ size_t i, n;
+ char *ret;
+
+ /* Count the size of the final string. */
+ n = 0;
+ for (i = 0; i < len; ++i) {
+ if (strncmp (&str[i], s1, s1len) == 0)
+ n += s2len;
+ else
+ n++;
+ }
+
+ ret = malloc (n+1);
+ if (ret == NULL)
+ return NULL;
+
+ n = 0;
+ for (i = 0; i < len; ++i) {
+ if (strncmp (&str[i], s1, s1len) == 0) {
+ strcpy (&ret[n], s2);
+ n += s2len;
+ }
+ else {
+ ret[n] = str[i];
+ n++;
+ }
+ }
+ ret[n] = '\0';
+
+ return ret;
+}
+
/**
* Translate a wait/system exit status into a printable string.
*/
diff --git a/lib/qemu.c b/lib/qemu.c
index 2f3493217..21450f996 100644
--- a/lib/qemu.c
+++ b/lib/qemu.c
@@ -903,37 +903,24 @@ guestfs_int_drive_source_qemu_param (guestfs_h *g,
}
case drive_protocol_rbd: {
+ CLEANUP_FREE_STRING_LIST char **hosts = NULL;
CLEANUP_FREE char *mon_host = NULL, *username = NULL, *secret = NULL;
const char *auth;
- size_t n = 0;
- size_t i, j;
+ size_t i;
- /* build the list of all the mon hosts */
- for (i = 0; i < src->nr_servers; i++) {
- n += strlen (src->servers[i].u.hostname);
- n += 8; /* for slashes, colons, & port numbers */
- }
- n++; /* for \0 */
- mon_host = safe_malloc (g, n);
- n = 0;
- for (i = 0; i < src->nr_servers; i++) {
- CLEANUP_FREE char *port = NULL;
+ /* Build the list of all the mon hosts. */
+ hosts = safe_calloc (g, src->nr_servers + 1, sizeof (char *));
- for (j = 0; j < strlen (src->servers[i].u.hostname); j++)
- mon_host[n++] = src->servers[i].u.hostname[j];
- mon_host[n++] = '\\';
- mon_host[n++] = ':';
- port = safe_asprintf (g, "%d", src->servers[i].port);
- for (j = 0; j < strlen (port); j++)
- mon_host[n++] = port[j];
+ for (i = 0; i < src->nr_servers; i++) {
+ CLEANUP_FREE char *escaped_host;
- /* join each host with \; */
- if (i != src->nr_servers - 1) {
- mon_host[n++] = '\\';
- mon_host[n++] = ';';
- }
+ escaped_host =
+ guestfs_int_replace_string (src->servers[i].u.hostname, ":", "\\:");
+ if (escaped_host == NULL) g->abort_cb ();
+ hosts[i] =
+ safe_asprintf (g, "%s\\:%d", escaped_host, src->servers[i].port);
}
- mon_host[n] = '\0';
+ mon_host = guestfs_int_join_strings ("\\;", hosts);
if (src->username)
username = safe_asprintf (g, ":id=%s", src->username);
--
2.20.1
More information about the Libguestfs
mailing list