]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Improve error reporting for virConnectOpen URIs
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 12 Jun 2009 12:06:15 +0000 (12:06 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 12 Jun 2009 12:06:15 +0000 (12:06 +0000)
ChangeLog
src/lxc_driver.c
src/openvz_driver.c
src/qemu_driver.c
src/remote_internal.c
src/test.c
src/uml_driver.c
src/virterror.c
src/xen_unified.c
src/xend_internal.c

index 53d8faa4ee6e45d5ae299a7aae65c5557fcb04f2..4ef02d263f88a6a18b16dba2e032c5b9cd7dfb45 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Thu Jun 12 13:06:42 BST 2009 Daniel P. Berrange <berrange@redhat.com>
+
+       Improve error reporting for virConnecOpen URIs
+       * src/lxc_driver.c, src/openvz_driver.c, src/qemu_driver.c,
+       src/uml_driver.c, src/xen_unified.c: Always return ACCEPT
+       or ERROR for URIs without hostname set, but with the driver's
+       matching URI scheme. ie never decline a correct URI
+       * src/xend_internal.c: Default port to 8000 if not given
+       in the http:// URI.
+       * src/remote_internal.c: Accept all URIs not handled by an
+       earlier driver.
+       * src/virterror.c: Improve error message text for
+       VIR_ERR_NO_CONNECT code
+
 Thu Jun 12 12:26:42 BST 2009 Daniel P. Berrange <berrange@redhat.com>
 
        Fix re-detection of transient VMs after libvirtd restart
index 6cdcbf3a8a48c1b18f184edcc22a747093504530..b286425ab82ad82c2d623e5696c7b60cb8b5cf89 100644 (file)
@@ -68,46 +68,48 @@ static void lxcDriverUnlock(lxc_driver_t *driver)
 }
 
 
-static int lxcProbe(void)
-{
-    if (getuid() != 0 ||
-        lxcContainerAvailable(0) < 0)
-        return 0;
-
-    return 1;
-}
-
 static virDrvOpenStatus lxcOpen(virConnectPtr conn,
                                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                 int flags ATTRIBUTE_UNUSED)
 {
-    if (lxc_driver == NULL)
-        goto declineConnection;
-
     /* Verify uri was specified */
     if (conn->uri == NULL) {
-        if (!lxcProbe())
-            goto declineConnection;
+        if (lxc_driver == NULL)
+            return VIR_DRV_OPEN_DECLINED;
 
         conn->uri = xmlParseURI("lxc:///");
         if (!conn->uri) {
             virReportOOMError(conn);
             return VIR_DRV_OPEN_ERROR;
         }
-    } else if (conn->uri->scheme == NULL ||
-               STRNEQ(conn->uri->scheme, "lxc")) {
-        goto declineConnection;
-    } else if (!lxcProbe()) {
-        goto declineConnection;
-    }
+    } else {
+        if (conn->uri->scheme == NULL ||
+            STRNEQ(conn->uri->scheme, "lxc"))
+            return VIR_DRV_OPEN_DECLINED;
 
+        /* Leave for remote driver */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* If path isn't '/' then they typoed, tell them correct path */
+        if (STRNEQ(conn->uri->path, "/")) {
+            lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected LXC URI path '%s', try lxc:///"),
+                     conn->uri->path);
+            return VIR_DRV_OPEN_ERROR;
+        }
+
+        /* URI was good, but driver isn't active */
+        if (lxc_driver == NULL) {
+            lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
+                     _("lxc state driver is not active"));
+            return VIR_DRV_OPEN_ERROR;
+        }
+    }
 
     conn->privateData = lxc_driver;
 
     return VIR_DRV_OPEN_SUCCESS;
-
-declineConnection:
-    return VIR_DRV_OPEN_DECLINED;
 }
 
 static int lxcClose(virConnectPtr conn)
index 4c0fc5f87cad043508ae3d042f9664e2c77ef3a7..85f61730052a2660b4bced7c7e75f1c28bb894b6 100644 (file)
@@ -1070,36 +1070,59 @@ cleanup:
     return ret;
 }
 
-static int openvzProbe(void)
-{
-    if (geteuid() == 0 &&
-        virFileExists("/proc/vz"))
-        return 1;
-
-    return 0;
-}
-
 static virDrvOpenStatus openvzOpen(virConnectPtr conn,
                                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                    int flags ATTRIBUTE_UNUSED)
 {
     struct openvz_driver *driver;
-    if (!openvzProbe())
-        return VIR_DRV_OPEN_DECLINED;
 
     if (conn->uri == NULL) {
+        if (!virFileExists("/proc/vz"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        if (access("/proc/vz", W_OK) < 0)
+            return VIR_DRV_OPEN_DECLINED;
+
         conn->uri = xmlParseURI("openvz:///system");
         if (conn->uri == NULL) {
-            openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
+            virReportOOMError(conn);
+            return VIR_DRV_OPEN_ERROR;
+        }
+    } else {
+        /* If scheme isn't 'openvz', then its for another driver */
+        if (conn->uri->scheme == NULL ||
+            STRNEQ (conn->uri->scheme, "openvz"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* If server name is given, its for remote driver */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* If path isn't /system, then they typoed, so tell them correct path */
+        if (conn->uri->path == NULL ||
+            STRNEQ (conn->uri->path, "/system")) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("unexpected OpenVZ URI path '%s', try openvz:///system"),
+                        conn->uri->path);
+            return VIR_DRV_OPEN_ERROR;
+        }
+
+        if (!virFileExists("/proc/vz")) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("OpenVZ control file /proc/vz does not exist"));
+            return VIR_DRV_OPEN_ERROR;
+        }
+
+        if (access("/proc/vz", W_OK) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("OpenVZ control file /proc/vz is not accessible"));
             return VIR_DRV_OPEN_ERROR;
         }
-    } else if (conn->uri->scheme == NULL ||
-               conn->uri->path == NULL ||
-               STRNEQ (conn->uri->scheme, "openvz") ||
-               STRNEQ (conn->uri->path, "/system")) {
-        return VIR_DRV_OPEN_DECLINED;
     }
 
+    /* We now know the URI is definitely for this driver, so beyond
+     * here, don't return DECLINED, always use ERROR */
+
     if (VIR_ALLOC(driver) < 0) {
         virReportOOMError(conn);
         return VIR_DRV_OPEN_ERROR;
index 5f94bed7eef15287bd9570dd13ae96239f432f5f..4a02840eabba4f1ff4840bb0bd6716c06639460a 100644 (file)
@@ -1743,62 +1743,61 @@ qemudMonitorCommand(const virDomainObjPtr vm,
 }
 
 
-/**
- * qemudProbe:
- *
- * Probe for the availability of the qemu driver, assume the
- * presence of QEmu emulation if the binaries are installed
- */
-static int qemudProbe(void)
-{
-    if ((virFileExists("/usr/bin/qemu")) ||
-        (virFileExists("/usr/bin/qemu-kvm")) ||
-        (virFileExists("/usr/bin/kvm")) ||
-        (virFileExists("/usr/bin/xenner")))
-        return 1;
-
-    return 0;
-}
 
 static virDrvOpenStatus qemudOpen(virConnectPtr conn,
                                   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                   int flags ATTRIBUTE_UNUSED) {
     uid_t uid = getuid();
 
-    if (qemu_driver == NULL)
-        goto decline;
-
-    if (!qemudProbe())
-        goto decline;
-
     if (conn->uri == NULL) {
-        conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system");
+        if (qemu_driver == NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        conn->uri = xmlParseURI(uid == 0 ?
+                                "qemu:///system" :
+                                "qemu:///session");
         if (!conn->uri) {
             virReportOOMError(conn);
             return VIR_DRV_OPEN_ERROR;
         }
-    } else if (conn->uri->scheme == NULL ||
-               conn->uri->path == NULL)
-        goto decline;
+    } else {
+        /* If URI isn't 'qemu' its definitely not for us */
+        if (conn->uri->scheme == NULL ||
+            STRNEQ(conn->uri->scheme, "qemu"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* Allow remote driver to deal with URIs with hostname server */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        if (!uid) {
+            if (STRNEQ (conn->uri->path, "/system") &&
+                STRNEQ (conn->uri->path, "/session")) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 _("unexpected QEMU URI path '%s', try qemu:///system"),
+                                 conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        } else {
+            if (STRNEQ (conn->uri->path, "/session")) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 _("unexpected QEMU URI path '%s', try qemu:///session"),
+                                 conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        }
 
-    if (STRNEQ (conn->uri->scheme, "qemu"))
-        goto decline;
+        /* URI was good, but driver isn't active */
+        if (qemu_driver == NULL) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
+                             _("qemu state driver is not active"));
+            return VIR_DRV_OPEN_ERROR;
+        }
 
-    if (uid != 0) {
-        if (STRNEQ (conn->uri->path, "/session"))
-            goto decline;
-    } else { /* root */
-        if (STRNEQ (conn->uri->path, "/system") &&
-            STRNEQ (conn->uri->path, "/session"))
-            goto decline;
     }
-
     conn->privateData = qemu_driver;
 
     return VIR_DRV_OPEN_SUCCESS;
-
- decline:
-    return VIR_DRV_OPEN_DECLINED;
 }
 
 static int qemudClose(virConnectPtr conn) {
index 0363ba414560f952c4687e8ba104be6420ee40f1..e4fa1569c739d5c0e33cc7f3edfefa8dfeacbcc7 100644 (file)
@@ -305,21 +305,28 @@ remoteForkDaemon(virConnectPtr conn)
 
 enum virDrvOpenRemoteFlags {
     VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
-    VIR_DRV_OPEN_REMOTE_UNIX = (1 << 1),
-    VIR_DRV_OPEN_REMOTE_USER = (1 << 2),
-    VIR_DRV_OPEN_REMOTE_AUTOSTART = (1 << 3),
+    VIR_DRV_OPEN_REMOTE_USER      = (1 << 1), /* Use the per-user socket path */
+    VIR_DRV_OPEN_REMOTE_AUTOSTART = (1 << 2), /* Autostart a per-user daemon */
 };
 
-/* What transport? */
-enum {
-    trans_tls,
-    trans_unix,
-    trans_ssh,
-    trans_ext,
-    trans_tcp,
-} transport;
-
 
+/*
+ * URIs that this driver needs to handle:
+ *
+ * The easy answer:
+ *   - Everything that no one else has yet claimed, but nothing if
+ *     we're inside the libvirtd daemon
+ *
+ * The hard answer:
+ *   - Plain paths (///var/lib/xen/xend-socket)  -> UNIX domain socket
+ *   - xxx://servername/      -> TLS connection
+ *   - xxx+tls://servername/  -> TLS connection
+ *   - xxx+tls:///            -> TLS connection to localhost
+ *   - xxx+tcp://servername/  -> TCP connection
+ *   - xxx+tcp:///            -> TCP connection to localhost
+ *   - xxx+unix:///           -> UNIX domain socket
+ *   - xxx:///                -> UNIX domain socket
+ */
 static int
 doRemoteOpen (virConnectPtr conn,
               struct private_data *priv,
@@ -328,37 +335,51 @@ doRemoteOpen (virConnectPtr conn,
 {
     int wakeupFD[2] = { -1, -1 };
     char *transport_str = NULL;
+    enum {
+        trans_tls,
+        trans_unix,
+        trans_ssh,
+        trans_ext,
+        trans_tcp,
+    } transport;
 
-    if (conn->uri) {
-        if (!conn->uri->scheme)
-            return VIR_DRV_OPEN_DECLINED;
-
-        transport_str = get_transport_from_scheme (conn->uri->scheme);
+    /* We handle *ALL*  URIs here. The caller has rejected any
+     * URIs we don't care about */
 
-        if (!transport_str || STRCASEEQ (transport_str, "tls"))
-            transport = trans_tls;
-        else if (STRCASEEQ (transport_str, "unix"))
+    if (conn->uri) {
+        if (!conn->uri->scheme) {
+            /* This is the ///var/lib/xen/xend-socket local path style */
             transport = trans_unix;
-        else if (STRCASEEQ (transport_str, "ssh"))
-            transport = trans_ssh;
-        else if (STRCASEEQ (transport_str, "ext"))
-            transport = trans_ext;
-        else if (STRCASEEQ (transport_str, "tcp"))
-            transport = trans_tcp;
-        else {
-            error (conn, VIR_ERR_INVALID_ARG,
-                   _("remote_open: transport in URL not recognised "
-                     "(should be tls|unix|ssh|ext|tcp)"));
-            return VIR_DRV_OPEN_ERROR;
-        }
-    }
+        } else {
+            transport_str = get_transport_from_scheme (conn->uri->scheme);
 
-    if (!transport_str) {
-        if ((!conn->uri || !conn->uri->server) &&
-            (flags & VIR_DRV_OPEN_REMOTE_UNIX))
-            transport = trans_unix;
-        else
-            return VIR_DRV_OPEN_DECLINED; /* Decline - not a remote URL. */
+            if (!transport_str) {
+                if (conn->uri->server)
+                    transport = trans_tls;
+                else
+                    transport = trans_unix;
+            } else {
+                if (STRCASEEQ (transport_str, "tls"))
+                    transport = trans_tls;
+                else if (STRCASEEQ (transport_str, "unix"))
+                    transport = trans_unix;
+                else if (STRCASEEQ (transport_str, "ssh"))
+                    transport = trans_ssh;
+                else if (STRCASEEQ (transport_str, "ext"))
+                    transport = trans_ext;
+                else if (STRCASEEQ (transport_str, "tcp"))
+                    transport = trans_tcp;
+                else {
+                    error (conn, VIR_ERR_INVALID_ARG,
+                           _("remote_open: transport in URL not recognised "
+                             "(should be tls|unix|ssh|ext|tcp)"));
+                    return VIR_DRV_OPEN_ERROR;
+                }
+            }
+        }
+    } else {
+        /* No URI, then must be probing so use UNIX socket */
+        transport = trans_unix;
     }
 
     /* Local variables which we will initialise. These can
@@ -455,8 +476,9 @@ doRemoteOpen (virConnectPtr conn,
 
         /* Construct the original name. */
         if (!name) {
-            if (STREQ(conn->uri->scheme, "remote") ||
-                STRPREFIX(conn->uri->scheme, "remote+")) {
+            if (conn->uri->scheme &&
+                (STREQ(conn->uri->scheme, "remote") ||
+                 STRPREFIX(conn->uri->scheme, "remote+"))) {
                 /* Allow remote serve to probe */
                 name = strdup("");
             } else {
@@ -580,7 +602,7 @@ doRemoteOpen (virConnectPtr conn,
 
         freeaddrinfo (res);
         virReportSystemError(conn, saved_errno,
-                             _("unable to connect to '%s'"),
+                             _("unable to connect to libvirtd at '%s'"),
                              priv->hostname);
         goto failed;
 
@@ -925,7 +947,6 @@ remoteOpenSecondaryDriver(virConnectPtr conn,
 
     if (flags & VIR_CONNECT_RO)
         rflags |= VIR_DRV_OPEN_REMOTE_RO;
-    rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
 
     ret = doRemoteOpen(conn, *priv, auth, rflags);
     if (ret != VIR_DRV_OPEN_SUCCESS) {
@@ -956,19 +977,6 @@ remoteOpen (virConnectPtr conn,
     if (flags & VIR_CONNECT_RO)
         rflags |= VIR_DRV_OPEN_REMOTE_RO;
 
-    /*
-     * If no servername is given, and no +XXX
-     * transport is listed, then force to a
-     * local UNIX socket connection
-     */
-    if (conn->uri &&
-        !conn->uri->server &&
-        conn->uri->scheme &&
-        !strchr(conn->uri->scheme, '+')) {
-        DEBUG0("Auto-remote UNIX socket");
-        rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
-    }
-
     /*
      * If no servername is given, and no +XXX
      * transport is listed, or transport is unix,
@@ -996,7 +1004,6 @@ remoteOpen (virConnectPtr conn,
      */
     if (!conn->uri) {
         DEBUG0("Auto-probe remote URI");
-        rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
 #ifndef __sun
         if (getuid() > 0) {
             DEBUG0("Auto-spawn user daemon instance");
index ba9ad6620cc3db42559d11f4022a302a5438b170..7dc0840e6132cc24be9a2b7a6fa9044ae3bc9032 100644 (file)
@@ -639,9 +639,6 @@ static virDrvOpenStatus testOpen(virConnectPtr conn,
     if (conn->uri->server)
         return VIR_DRV_OPEN_DECLINED;
 
-    if (conn->uri->server)
-        return VIR_DRV_OPEN_DECLINED;
-
     /* From this point on, the connection is for us. */
     if (!conn->uri->path
         || conn->uri->path[0] == '\0'
index 2df342c83a0a2650d9163993cce4f70b741e0756..d3e829ad910e8994e775486ccac564d9dccffa31 100644 (file)
@@ -913,28 +913,49 @@ static virDrvOpenStatus umlOpen(virConnectPtr conn,
                                 int flags ATTRIBUTE_UNUSED) {
     uid_t uid = getuid();
 
-    if (uml_driver == NULL)
-        goto decline;
+    if (conn->uri == NULL) {
+        if (uml_driver == NULL)
+            return VIR_DRV_OPEN_DECLINED;
 
-    if (conn->uri != NULL) {
-        if (conn->uri->scheme == NULL || conn->uri->path == NULL)
-            goto decline;
+        conn->uri = xmlParseURI(uid == 0 ?
+                                "uml:///system" :
+                                "uml:///session");
+        if (!conn->uri) {
+            virReportOOMError(conn);
+            return VIR_DRV_OPEN_ERROR;
+        }
+    } else {
+        if (conn->uri->scheme == NULL ||
+            STRNEQ (conn->uri->scheme, "uml"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* Allow remote driver to deal with URIs with hostname server */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
 
-        if (STRNEQ (conn->uri->scheme, "uml"))
-            goto decline;
 
-        if (uid != 0) {
-            if (STRNEQ (conn->uri->path, "/session"))
-                goto decline;
-        } else { /* root */
+        /* Check path and tell them correct path if they made a mistake */
+        if (uid == 0) {
             if (STRNEQ (conn->uri->path, "/system") &&
-                STRNEQ (conn->uri->path, "/session"))
-                goto decline;
+                STRNEQ (conn->uri->path, "/session")) {
+                umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected UML URI path '%s', try uml:///system"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        } else {
+            if (STRNEQ (conn->uri->path, "/session")) {
+                umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected UML URI path '%s', try uml:///session"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
         }
-    } else {
-        conn->uri = xmlParseURI(uid ? "uml:///session" : "uml:///system");
-        if (!conn->uri) {
-            virReportOOMError(conn);
+
+        /* URI was good, but driver isn't active */
+        if (uml_driver == NULL) {
+            umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("uml state driver is not active"));
             return VIR_DRV_OPEN_ERROR;
         }
     }
@@ -942,9 +963,6 @@ static virDrvOpenStatus umlOpen(virConnectPtr conn,
     conn->privateData = uml_driver;
 
     return VIR_DRV_OPEN_SUCCESS;
-
- decline:
-    return VIR_DRV_OPEN_DECLINED;
 }
 
 static int umlClose(virConnectPtr conn) {
index b1bf3911336b5c011bce55753e059ffa7b2e69e8..b1c9ba4be097397bf959ba04619ac5d924ca0f55 100644 (file)
@@ -737,9 +737,9 @@ virErrorMsg(virErrorNumber error, const char *info)
             break;
         case VIR_ERR_NO_CONNECT:
             if (info == NULL)
-                errmsg = _("could not connect to hypervisor");
+                errmsg = _("no hypervisor driver available");
             else
-                errmsg = _("could not connect to %s");
+                errmsg = _("no hypervisor driver available for %s");
             break;
         case VIR_ERR_INVALID_CONN:
             if (info == NULL)
index 57efb40a14e228eb9e3c6a13d0eac89002cb8617..2535f99e8e5313e9f4c7a69e30642b19cabf2a71 100644 (file)
@@ -241,25 +241,46 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
             virReportOOMError (NULL);
             return VIR_DRV_OPEN_ERROR;
         }
-    }
-
-    /* Refuse any scheme which isn't "xen://" or "http://". */
-    if (conn->uri->scheme &&
-        STRCASENEQ(conn->uri->scheme, "xen") &&
-        STRCASENEQ(conn->uri->scheme, "http"))
-        return VIR_DRV_OPEN_DECLINED;
+    } else {
+        if (conn->uri->scheme) {
+            /* Decline any scheme which isn't "xen://" or "http://". */
+            if (STRCASENEQ(conn->uri->scheme, "xen") &&
+                STRCASENEQ(conn->uri->scheme, "http"))
+                return VIR_DRV_OPEN_DECLINED;
+
+
+            /* Return an error if the path isn't '' or '/' */
+            if (conn->uri->path &&
+                STRNEQ(conn->uri->path, "") &&
+                STRNEQ(conn->uri->path, "/")) {
+                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                _("unexpected Xen URI path '%s', try xen:///"),
+                                conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
 
-    /* xmlParseURI will parse a naked string like "foo" as a URI with
-     * a NULL scheme.  That's not useful for us because we want to only
-     * allow full pathnames (eg. ///var/lib/xen/xend-socket).  Decline
-     * anything else.
-     */
-    if (!conn->uri->scheme && (!conn->uri->path || conn->uri->path[0] != '/'))
-        return VIR_DRV_OPEN_DECLINED;
+            /* Decline any xen:// URI with a server specified, allowing remote
+             * driver to handle, but keep any http:/// URIs */
+            if (STRCASEEQ(conn->uri->scheme, "xen") &&
+                conn->uri->server)
+                return VIR_DRV_OPEN_DECLINED;
+        } else {
+            /* Special case URI for Xen driver only:
+             *
+             * Treat a plain path as a Xen UNIX socket path, and give
+             * error unless path is absolute
+             */
+            if (!conn->uri->path || conn->uri->path[0] != '/') {
+                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                _("unexpected Xen URI path '%s', try ///var/lib/xen/xend-socket"),
+                                NULLSTR(conn->uri->path));
+                return VIR_DRV_OPEN_ERROR;
+            }
+        }
+    }
 
-    /* Refuse any xen:// URI with a server specified - allow remote to do it */
-    if (conn->uri->scheme && STRCASEEQ(conn->uri->scheme, "xen") && conn->uri->server)
-        return VIR_DRV_OPEN_DECLINED;
+    /* We now know the URI is definitely for this driver, so beyond
+     * here, don't return DECLINED, always use ERROR */
 
     /* Allocate per-connection private data. */
     if (VIR_ALLOC(priv) < 0) {
index 94aaa42e875c11d92ac658cae2150286fcf29d0f..b211bb6293355bf68e33f56f947021bd7bb8e675 100644 (file)
@@ -2927,10 +2927,13 @@ xenDaemonOpen(virConnectPtr conn,
             xend_detect_config_version(conn) == -1)
             goto failed;
     } else if (STRCASEEQ (conn->uri->scheme, "http")) {
-        if (virAsprintf(&port, "%d", conn->uri->port) == -1)
+        if (conn->uri->port &&
+            virAsprintf(&port, "%d", conn->uri->port) == -1)
             goto failed;
 
-        if (xenDaemonOpen_tcp(conn, conn->uri->server, port) < 0 ||
+        if (xenDaemonOpen_tcp(conn,
+                              conn->uri->server ? conn->uri->server : "localhost",
+                              port ? port : "8000") < 0 ||
             xend_detect_config_version(conn) == -1)
             goto failed;
     } else {