[libvirt] [PATCH] Better error reporting for failed migration.

Chris Lalancette clalance at redhat.com
Thu Feb 18 15:38:37 UTC 2010


If the hostname as returned by "gethostname" resolves
to "localhost" (as it does with the broken Fedora-12
installer), then live migration will fail because the
source will try to migrate to itself.  Detect this
situation up-front and abort the live migration before
we do any real work.

Signed-off-by: Chris Lalancette <clalance at redhat.com>
---
 src/libvirt_private.syms |    1 +
 src/qemu/qemu_driver.c   |    2 +-
 src/util/util.c          |   37 +++++++++++++++++++++++++++++++++++--
 src/util/util.h          |    1 +
 4 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e3806cd..69ad686 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -568,6 +568,7 @@ virExecDaemonize;
 virSetCloseExec;
 virSetNonBlock;
 virFormatMacAddr;
+virGetHostnameLocalhost;
 virGetHostname;
 virParseMacAddr;
 virFileDeletePid;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d8ec04..2123880 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7748,7 +7748,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
         if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
 
         /* Get hostname */
-        if ((hostname = virGetHostname(dconn)) == NULL)
+        if ((hostname = virGetHostnameLocalhost(0)) == NULL)
             goto cleanup;
 
         /* XXX this really should have been a properly well-formed
diff --git a/src/util/util.c b/src/util/util.c
index cdab300..72cc222 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2193,11 +2193,11 @@ char *virIndexToDiskName(int idx, const char *prefix)
 #define AI_CANONIDN 0
 #endif
 
-char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
+char *virGetHostnameLocalhost(int allow_localhost)
 {
     int r;
     char hostname[HOST_NAME_MAX+1], *result;
-    struct addrinfo hints, *info;
+    struct addrinfo hints, *info, *res;
 
     r = gethostname (hostname, sizeof(hostname));
     if (r == -1) {
@@ -2217,6 +2217,34 @@ char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
                      hostname, gai_strerror(r));
         return NULL;
     }
+
+    /* if we aren't allowing localhost, then we iterate through the
+     * list and make sure none of the IPv4 addresses are 127.0.0.1 and
+     * that none of the IPv6 addresses are ::1
+     */
+    if (!allow_localhost) {
+        res = info;
+        while (res) {
+            if (res->ai_family == AF_INET) {
+                if (htonl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr) == INADDR_LOOPBACK) {
+                    virUtilError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                 _("canonical hostname pointed to localhost, but this is not allowed"));
+                    freeaddrinfo(info);
+                    return NULL;
+                }
+            }
+            else if (res->ai_family == AF_INET6) {
+                if (IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
+                    virUtilError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                 _("canonical hostname pointed to localhost, but this is not allowed"));
+                    freeaddrinfo(info);
+                    return NULL;
+                }
+            }
+            res = res->ai_next;
+        }
+    }
+
     if (info->ai_canonname == NULL) {
         virUtilError(VIR_ERR_INTERNAL_ERROR,
                      "%s", _("could not determine canonical host name"));
@@ -2233,6 +2261,11 @@ char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
     return result;
 }
 
+char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return virGetHostnameLocalhost(1);
+}
+
 /* send signal to a single process */
 int virKillProcess(pid_t pid, int sig)
 {
diff --git a/src/util/util.h b/src/util/util.h
index 4207508..d024fe1 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -232,6 +232,7 @@ static inline int getuid (void) { return 0; }
 static inline int getgid (void) { return 0; }
 #endif
 
+char *virGetHostnameLocalhost(int allow_localhost);
 char *virGetHostname(virConnectPtr conn);
 
 int virKillProcess(pid_t pid, int sig);
-- 
1.6.6




More information about the libvir-list mailing list