Index: include/libvirt/libvirt.h
===================================================================
RCS file: /data/cvs/libvirt/include/libvirt/libvirt.h,v
retrieving revision 1.47
diff -u -p -r1.47 libvirt.h
--- include/libvirt/libvirt.h	25 Jun 2007 15:56:18 -0000	1.47
+++ include/libvirt/libvirt.h	26 Jun 2007 09:50:51 -0000
@@ -272,6 +272,10 @@ int			virConnectClose		(virConnectPtr co
 const char *		virConnectGetType	(virConnectPtr conn);
 int			virConnectGetVersion	(virConnectPtr conn,
 						 unsigned long *hvVer);
+char *                  virConnectGetHostname   (virConnectPtr conn);
+char *                  virConnectGetURI        (virConnectPtr conn);
+
+
 /*
  * Capabilities of the connection / driver.
  */
Index: include/libvirt/libvirt.h.in
===================================================================
RCS file: /data/cvs/libvirt/include/libvirt/libvirt.h.in,v
retrieving revision 1.29
diff -u -p -r1.29 libvirt.h.in
--- include/libvirt/libvirt.h.in	25 Jun 2007 15:56:18 -0000	1.29
+++ include/libvirt/libvirt.h.in	26 Jun 2007 09:50:52 -0000
@@ -272,6 +272,10 @@ int			virConnectClose		(virConnectPtr co
 const char *		virConnectGetType	(virConnectPtr conn);
 int			virConnectGetVersion	(virConnectPtr conn,
 						 unsigned long *hvVer);
+char *                  virConnectGetHostname   (virConnectPtr conn);
+char *                  virConnectGetURI        (virConnectPtr conn);
+
+
 /*
  * Capabilities of the connection / driver.
  */
Index: qemud/remote.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote.c,v
retrieving revision 1.3
diff -u -p -r1.3 remote.c
--- qemud/remote.c	25 Jun 2007 08:23:10 -0000	1.3
+++ qemud/remote.c	26 Jun 2007 09:50:53 -0000
@@ -460,6 +460,22 @@ remoteDispatchGetVersion (struct qemud_c
 }
 
 static int
+remoteDispatchGetHostname (struct qemud_client *client,
+                           remote_message_header *req,
+                           void *args ATTRIBUTE_UNUSED,
+                           remote_get_hostname_ret *ret)
+{
+    char *hostname;
+    CHECK_CONN(client);
+
+    hostname = virConnectGetHostname (client->conn);
+    if (hostname == NULL) return -1;
+
+    ret->hostname = hostname;
+    return 0;
+}
+
+static int
 remoteDispatchGetMaxVcpus (struct qemud_client *client,
                            remote_message_header *req,
                            remote_get_max_vcpus_args *args,
Index: qemud/remote_protocol.x
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote_protocol.x,v
retrieving revision 1.2
diff -u -p -r1.2 remote_protocol.x
--- qemud/remote_protocol.x	22 Jun 2007 13:16:10 -0000	1.2
+++ qemud/remote_protocol.x	26 Jun 2007 09:50:53 -0000
@@ -178,6 +178,10 @@ struct remote_get_version_ret {
     hyper hv_ver;
 };
 
+struct remote_get_hostname_ret {
+    remote_nonnull_string hostname;
+};
+
 struct remote_get_max_vcpus_args {
     /* The only backend which supports this call is Xen HV, and
      * there the type is ignored so it could be NULL.
@@ -605,7 +609,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_SAVE = 55,
     REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE = 56,
     REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57,
-    REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58
+    REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58,
+    REMOTE_PROC_GET_HOSTNAME = 59
 };
 
 /* Custom RPC structure. */
Index: src/driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/driver.h,v
retrieving revision 1.28
diff -u -p -r1.28 driver.h
--- src/driver.h	11 Jun 2007 11:43:41 -0000	1.28
+++ src/driver.h	26 Jun 2007 09:50:53 -0000
@@ -54,6 +54,10 @@ typedef const char *
 typedef int
 	(*virDrvGetVersion)		(virConnectPtr conn,
 					 unsigned long *hvVer);
+typedef char *
+    (*virDrvGetHostname)    (virConnectPtr conn);
+typedef char *
+    (*virDrvGetURI)         (virConnectPtr conn);
 typedef int
 	(*virDrvGetMaxVcpus)		(virConnectPtr conn,
 					 const char *type);
@@ -199,6 +203,8 @@ struct _virDriver {
 	virDrvClose			close;
 	virDrvGetType			type;
 	virDrvGetVersion		version;
+    virDrvGetHostname       getHostname;
+    virDrvGetURI            getURI;
 	virDrvGetMaxVcpus		getMaxVcpus;
 	virDrvNodeGetInfo		nodeGetInfo;
 	virDrvGetCapabilities		getCapabilities;
Index: src/internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/internal.h,v
retrieving revision 1.43
diff -u -p -r1.43 internal.h
--- src/internal.h	22 Jun 2007 11:42:22 -0000	1.43
+++ src/internal.h	26 Jun 2007 09:50:54 -0000
@@ -34,6 +34,8 @@ extern "C" {
 /* String equality tests, suggested by Jim Meyering. */
 #define STREQ(a,b) (strcmp((a),(b)) == 0)
 #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
+#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
+#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
 
 /**
  * ATTRIBUTE_UNUSED:
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.79
diff -u -p -r1.79 libvirt.c
--- src/libvirt.c	25 Jun 2007 15:56:18 -0000	1.79
+++ src/libvirt.c	26 Jun 2007 09:50:55 -0000
@@ -466,6 +466,63 @@ virConnectGetVersion(virConnectPtr conn,
 }
 
 /**
+ * virConnectGetHostname:
+ * @conn: pointer to a hypervisor connection
+ *
+ * This returns the system hostname on which the hypervisor is
+ * running (the result of the gethostname(2) system call).  If
+ * we are connected to a remote system, then this returns the
+ * hostname of the remote system.
+ *
+ * Returns the hostname which must be freed by the caller, or
+ * NULL if there was an error.
+ */
+char *
+virConnectGetHostname (virConnectPtr conn)
+{
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return NULL;
+    }
+
+    if (conn->driver->getHostname)
+        return conn->driver->getHostname (conn);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+/**
+ * virConnectGetURI:
+ * @conn: pointer to a hypervisor connection
+ *
+ * This returns the URI (name) of the hypervisor connection.
+ * Normally this is the same as or similar to the string passed
+ * to the virConnectOpen/virConnectOpenReadOnly call, but
+ * the driver may make the URI canonical.  If name == NULL
+ * was passed to virConnectOpen, then the driver will return
+ * a non-NULL URI which can be used to connect to the same
+ * hypervisor later.
+ *
+ * Returns the URI string which must be freed by the caller, or
+ * NULL if there was an error.
+ */
+char *
+virConnectGetURI (virConnectPtr conn)
+{
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return NULL;
+    }
+
+    if (conn->driver->getURI)
+        return conn->driver->getURI (conn);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+/**
  * virConnectGetMaxVcpus:
  * @conn: pointer to the hypervisor connection
  * @type: value of the 'type' attribute in the <domain> element
Index: src/libvirt_sym.version
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt_sym.version,v
retrieving revision 1.22
diff -u -p -r1.22 libvirt_sym.version
--- src/libvirt_sym.version	25 Jun 2007 15:56:18 -0000	1.22
+++ src/libvirt_sym.version	26 Jun 2007 09:50:55 -0000
@@ -6,6 +6,8 @@
 	virConnectClose;
 	virConnectGetType;
 	virConnectGetVersion;
+	virConnectGetHostname;
+	virConnectGetURI;
 	virDomainGetConnect;
 	virConnectListDomains;
 	virConnectNumOfDomains;
Index: src/proxy_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/proxy_internal.c,v
retrieving revision 1.30
diff -u -p -r1.30 proxy_internal.c
--- src/proxy_internal.c	15 Jun 2007 15:24:20 -0000	1.30
+++ src/proxy_internal.c	26 Jun 2007 09:50:56 -0000
@@ -53,6 +53,8 @@ virDriver xenProxyDriver = {
     xenProxyClose, /* close */
     NULL, /* type */
     xenProxyGetVersion, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     NULL, /* getMaxVcpus */
     xenProxyNodeGetInfo, /* nodeGetInfo */
     xenProxyGetCapabilities, /* getCapabilities */
Index: src/qemu_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_internal.c,v
retrieving revision 1.28
diff -u -p -r1.28 qemu_internal.c
--- src/qemu_internal.c	20 Jun 2007 17:25:39 -0000	1.28
+++ src/qemu_internal.c	26 Jun 2007 09:50:57 -0000
@@ -1023,13 +1023,16 @@ static int qemuNetworkOpen(virConnectPtr
         return VIR_DRV_OPEN_ERROR;
     }
 
-    if (!strcmp(conn->driver->name, "QEMU")) {
+    if (STREQ (conn->driver->name, "QEMU")) {
         /* QEMU driver is active - just re-use existing connection */
         qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
         netpriv->qemud_fd = priv->qemud_fd;
         netpriv->shared = 1;
         conn->networkPrivateData = netpriv;
         return VIR_DRV_OPEN_SUCCESS;
+    } else if (STREQ (conn->driver->name, "remote")) {
+        /* Remote has its own network driver. */
+        return VIR_DRV_OPEN_SUCCESS;
     } else {
         /* Non-QEMU driver is active - open a new connection */
         const char *drvname = geteuid() == 0 ? "qemu:///system" : "qemu:///session";
@@ -1052,12 +1055,15 @@ static int qemuNetworkOpen(virConnectPtr
 static int
 qemuNetworkClose (virConnectPtr conn)
 {
-    qemuNetworkPrivatePtr netpriv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
-
-    if (!netpriv->shared)
-        close(netpriv->qemud_fd);
-    free(netpriv);
-    conn->networkPrivateData = NULL;
+    if (STRNEQ (conn->driver->name, "remote")) {
+        qemuNetworkPrivatePtr netpriv =
+            (qemuNetworkPrivatePtr) conn->networkPrivateData;
+
+        if (!netpriv->shared)
+            close(netpriv->qemud_fd);
+        free(netpriv);
+        conn->networkPrivateData = NULL;
+    }
 
     return 0;
 }
@@ -1380,6 +1386,8 @@ static virDriver qemuDriver = {
     qemuClose, /* close */
     NULL, /* type */
     qemuGetVersion, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     NULL, /* getMaxVcpus */
     qemuNodeGetInfo, /* nodeGetInfo */
     qemuGetCapabilities, /* getCapabilities */
Index: src/remote_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/remote_internal.c,v
retrieving revision 1.7
diff -u -p -r1.7 remote_internal.c
--- src/remote_internal.c	25 Jun 2007 13:05:03 -0000	1.7
+++ src/remote_internal.c	26 Jun 2007 09:50:59 -0000
@@ -58,6 +58,7 @@ struct private_data {
     gnutls_session_t session;   /* GnuTLS session (if uses_tls != 0). */
     char *type;                 /* Cached return from remoteType. */
     int counter;                /* Generates serial numbers for RPC. */
+    char *uri;                  /* Original (remote) URI. */
 };
 
 #define GET_PRIVATE(conn,retcode)                                       \
@@ -148,19 +149,23 @@ remoteOpen (virConnectPtr conn, const ch
         return VIR_DRV_OPEN_ERROR;
     }
 
-    /* Return code from this function, and the private data. */
-    int retcode = VIR_DRV_OPEN_ERROR;
-    struct private_data priv = { .magic = DEAD, .sock = -1 };
+    /* Local variables which we will initialise. These can
+     * get freed in the failed: path.
+     */
     char *name = 0, *command = 0, *sockname = 0, *netcat = 0, *username = 0;
-    char *server, *port;
+    char *server = 0, *port = 0;
     int no_verify = 0;
     char **cmd_argv = 0;
 
+    /* Return code from this function, and the private data. */
+    int retcode = VIR_DRV_OPEN_ERROR;
+    struct private_data priv = { .magic = DEAD, .sock = -1 };
+
     /* Remote server defaults to "localhost" if not specified. */
     server = strdup (uri->server ? uri->server : "localhost");
     if (!server) {
     out_of_memory:
-        error (NULL, VIR_ERR_NO_MEMORY, "remote_open");
+        error (NULL, VIR_ERR_NO_MEMORY, "duplicating server name");
         goto failed;
     }
     if (uri->port != 0) {
@@ -456,6 +461,14 @@ remoteOpen (virConnectPtr conn, const ch
         error (NULL, VIR_ERR_NO_MEMORY, "malloc");
         goto failed;
     }
+    /* Duplicate and save the uri_str. */
+    priv.uri = strdup (uri_str);
+    if (!priv.uri) {
+        error (NULL, VIR_ERR_NO_MEMORY, "allocating priv->uri");
+        free (conn->privateData);
+        goto failed;
+    }
+
     priv.magic = MAGIC;
     memcpy (conn->privateData, &priv, sizeof priv);
 
@@ -931,6 +944,13 @@ remoteClose (virConnectPtr conn)
     /* See comment for remoteType. */
     if (priv->type) free (priv->type);
 
+    /* Free URI copy. */
+    if (priv->uri) free (priv->uri);
+
+    /* Free private data. */
+    priv->magic = DEAD;
+    free (conn->privateData);
+
     return 0;
 }
 
@@ -977,6 +997,39 @@ remoteVersion (virConnectPtr conn, unsig
     return 0;
 }
 
+static char *
+remoteGetHostname (virConnectPtr conn)
+{
+    remote_get_hostname_ret ret;
+    GET_PRIVATE (conn, NULL);
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_get_hostname_ret, (char *) &ret) == -1)
+        return NULL;
+
+    /* Caller frees this. */
+    return ret.hostname;
+}
+
+/* This call is unusual because it doesn't go over RPC.  The
+ * full URI is known (only) at the client end of the connection.
+ */
+static char *
+remoteGetURI (virConnectPtr conn)
+{
+    GET_PRIVATE (conn, NULL);
+    char *str;
+
+    str = strdup (priv->uri);
+    if (str == NULL) {
+        error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    return str;
+}
+
 static int
 remoteGetMaxVcpus (virConnectPtr conn, const char *type)
 {
@@ -2604,6 +2657,8 @@ static virDriver driver = {
     .close = remoteClose,
 	.type = remoteType,
 	.version = remoteVersion,
+    .getHostname = remoteGetHostname,
+    .getURI = remoteGetURI,
 	.getMaxVcpus = remoteGetMaxVcpus,
 	.nodeGetInfo = remoteNodeGetInfo,
     .getCapabilities = remoteGetCapabilities,
Index: src/test.c
===================================================================
RCS file: /data/cvs/libvirt/src/test.c,v
retrieving revision 1.35
diff -u -p -r1.35 test.c
--- src/test.c	25 Jun 2007 13:26:02 -0000	1.35
+++ src/test.c	26 Jun 2007 09:51:00 -0000
@@ -22,9 +22,13 @@
  */
 
 #ifdef WITH_TEST
+
+#define _GNU_SOURCE /* for asprintf */
+
 #include <stdio.h>
 #include <string.h>
 #include <sys/time.h>
+#include <errno.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libxml/xpath.h>
@@ -42,6 +46,8 @@ int testOpen(virConnectPtr conn,
 int testClose  (virConnectPtr conn);
 int testGetVersion(virConnectPtr conn,
                    unsigned long *hvVer);
+char *testGetHostname (virConnectPtr conn);
+char *testGetURI (virConnectPtr conn);
 int testNodeGetInfo(virConnectPtr conn,
                     virNodeInfoPtr info);
 char *testGetCapabilities (virConnectPtr conn);
@@ -96,6 +102,8 @@ static virDriver testDriver = {
     testClose, /* close */
     NULL, /* type */
     testGetVersion, /* version */
+    testGetHostname, /* hostname */
+    testGetURI, /* URI */
     NULL, /* getMaxVcpus */
     testNodeGetInfo, /* nodeGetInfo */
     testGetCapabilities, /* getCapabilities */
@@ -140,6 +148,7 @@ static virDriver testDriver = {
 /* Per-connection private data. */
 struct _testPrivate {
     int handle;
+    char *path;
 };
 typedef struct _testPrivate *testPrivatePtr;
 
@@ -748,12 +757,17 @@ int testOpen(virConnectPtr conn,
     }
 
     /* Allocate per-connection private data. */
-    priv = conn->privateData = malloc (sizeof (struct _testPrivate));
+    priv = conn->privateData = calloc (1, sizeof (struct _testPrivate));
     if (!priv) {
         testError(NULL, NULL, VIR_ERR_NO_MEMORY, _("allocating private data"));
         return VIR_DRV_OPEN_ERROR;
     }
     priv->handle = -1;
+    priv->path = strdup (uri->path);
+    if (!priv->path) {
+        testError (NULL, NULL, VIR_ERR_NO_MEMORY, _("allocating path"));
+        return VIR_DRV_OPEN_ERROR;
+    }
 
     if (strcmp(uri->path, "/default") == 0) {
         ret = testOpenDefault(conn,
@@ -792,6 +806,7 @@ int testClose(virConnectPtr conn)
         memset (con, 0, sizeof *con); // RWMJ - why?
     }
 
+    free (priv->path);
     free (priv);
     return 0;
 }
@@ -803,6 +818,38 @@ int testGetVersion(virConnectPtr conn AT
     return (0);
 }
 
+char *
+testGetHostname (virConnectPtr conn)
+{
+    int r;
+    char hostname [HOST_NAME_MAX+1], *str;
+
+    r = gethostname (hostname, HOST_NAME_MAX+1);
+    if (r == -1) {
+        testError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    str = strdup (hostname);
+    if (str == NULL) {
+        testError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    return str;
+}
+
+char *
+testGetURI (virConnectPtr conn)
+{
+    testPrivatePtr priv = (testPrivatePtr) conn->privateData;
+    char *uri;
+
+    if (asprintf (&uri, "test://%s", priv->path) == -1) {
+        testError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    return uri;
+}
+
 int testNodeGetInfo(virConnectPtr conn,
                     virNodeInfoPtr info)
 {
Index: src/virsh.c
===================================================================
RCS file: /data/cvs/libvirt/src/virsh.c,v
retrieving revision 1.88
diff -u -p -r1.88 virsh.c
--- src/virsh.c	20 Jun 2007 17:22:09 -0000	1.88
+++ src/virsh.c	26 Jun 2007 09:51:02 -0000
@@ -2588,7 +2588,65 @@ cmdVersion(vshControl * ctl, vshCmd * cm
 }
 
 /*
- * "dumpxml" command
+ * "hostname" command
+ */
+static vshCmdInfo info_hostname[] = {
+    {"syntax", "hostname"},
+    {"help", gettext_noop("print the hypervisor hostname")},
+    {NULL, NULL}
+};
+
+static int
+cmdHostname (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *hostname;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    hostname = virConnectGetHostname (ctl->conn);
+    if (hostname == NULL) {
+        vshError(ctl, FALSE, _("failed to get hostname"));
+        return FALSE;
+    }
+
+    vshPrint (ctl, "%s\n", hostname);
+    free (hostname);
+
+    return TRUE;
+}
+
+/*
+ * "uri" command
+ */
+static vshCmdInfo info_uri[] = {
+    {"syntax", "uri"},
+    {"help", gettext_noop("print the hypervisor canonical URI")},
+    {NULL, NULL}
+};
+
+static int
+cmdURI (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *uri;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    uri = virConnectGetURI (ctl->conn);
+    if (uri == NULL) {
+        vshError(ctl, FALSE, _("failed to get URI"));
+        return FALSE;
+    }
+
+    vshPrint (ctl, "%s\n", uri);
+    free (uri);
+
+    return TRUE;
+}
+
+/*
+ * "vncdisplay" command
  */
 static vshCmdInfo info_vncdisplay[] = {
     {"syntax", "vncdisplay <domain>"},
@@ -3330,6 +3388,7 @@ static vshCmdDef commands[] = {
     {"domname", cmdDomname, opts_domname, info_domname},
     {"domstate", cmdDomstate, opts_domstate, info_domstate},
     {"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
+    {"hostname", cmdHostname, NULL, info_hostname},
     {"list", cmdList, opts_list, info_list},
     {"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
     {"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
@@ -3355,6 +3414,7 @@ static vshCmdDef commands[] = {
     {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
     {"suspend", cmdSuspend, opts_suspend, info_suspend},
     {"undefine", cmdUndefine, opts_undefine, info_undefine},
+    {"uri", cmdURI, NULL, info_uri},
     {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
     {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
     {"version", cmdVersion, NULL, info_version},
Index: src/xen_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_internal.c,v
retrieving revision 1.80
diff -u -p -r1.80 xen_internal.c
--- src/xen_internal.c	22 Jun 2007 11:42:22 -0000	1.80
+++ src/xen_internal.c	26 Jun 2007 09:51:04 -0000
@@ -597,6 +597,8 @@ virDriver xenHypervisorDriver = {
     xenHypervisorClose, /* close */
     xenHypervisorGetType, /* type */
     xenHypervisorGetVersion, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     xenHypervisorGetMaxVcpus, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     xenHypervisorGetCapabilities, /* getCapabilities */
Index: src/xen_unified.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.c,v
retrieving revision 1.13
diff -u -p -r1.13 xen_unified.c
--- src/xen_unified.c	25 Jun 2007 08:23:10 -0000	1.13
+++ src/xen_unified.c	26 Jun 2007 09:51:05 -0000
@@ -28,6 +28,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <xen/dom0_ops.h>
 #include <libxml/uri.h>
@@ -129,13 +130,20 @@ xenUnifiedOpen (virConnectPtr conn, cons
     xmlFreeURI(uri);
 
     /* Allocate per-connection private data. */
-    priv = malloc (sizeof *priv);
+    priv = calloc (1, sizeof *priv);
     if (!priv) {
         xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
         return VIR_DRV_OPEN_ERROR;
     }
     conn->privateData = priv;
 
+    priv->name = strdup (name);
+    if (!priv->name) {
+        xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating priv->name");
+        free (priv);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
     priv->handle = -1;
     priv->xendConfigVersion = -1;
     priv->type = -1;
@@ -165,6 +173,11 @@ xenUnifiedOpen (virConnectPtr conn, cons
         if (!priv->opened[i] && (getuid() == 0 || i == proxy_offset)) {
             for (j = 0; j < i; ++j)
                 if (priv->opened[j]) drivers[j]->close (conn);
+            free (priv->name);
+            free (priv);
+            /* The assumption is that one of the underlying drivers
+             * has set virterror already.
+             */
             return VIR_DRV_OPEN_ERROR;
         }
     }
@@ -185,6 +198,7 @@ xenUnifiedClose (virConnectPtr conn)
         if (priv->opened[i] && drivers[i]->close)
             (void) drivers[i]->close (conn);
 
+    free (priv->name);
     free (conn->privateData);
     conn->privateData = NULL;
 
@@ -222,6 +236,43 @@ xenUnifiedVersion (virConnectPtr conn, u
     return -1;
 }
 
+/* NB: Even if connected to the proxy, we're still on the
+ * same machine.
+ */
+static char *
+xenUnifiedGetHostname (virConnectPtr conn)
+{
+    int r;
+    char hostname [HOST_NAME_MAX+1], *str;
+
+    r = gethostname (hostname, HOST_NAME_MAX+1);
+    if (r == -1) {
+        xenUnifiedError (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    str = strdup (hostname);
+    if (str == NULL) {
+        xenUnifiedError (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    return str;
+}
+
+/* The name is recorded (canonicalised) in xenUnifiedOpen. */
+static char *
+xenUnifiedGetURI (virConnectPtr conn)
+{
+    GET_PRIVATE(conn);
+    char *str;
+
+    str = strdup (priv->name);
+    if (str == NULL) {
+        xenUnifiedError (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return NULL;
+    }
+    return str;
+}
+
 static int
 xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
 {
@@ -850,6 +901,8 @@ static virDriver xenUnifiedDriver = {
     .close 			= xenUnifiedClose,
     .type 			= xenUnifiedType,
     .version 			= xenUnifiedVersion,
+    .getHostname    = xenUnifiedGetHostname,
+    .getURI         = xenUnifiedGetURI,
     .getMaxVcpus 			= xenUnifiedGetMaxVcpus,
     .nodeGetInfo 			= xenUnifiedNodeGetInfo,
     .getCapabilities 		= xenUnifiedGetCapabilities,
Index: src/xen_unified.h
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.h,v
retrieving revision 1.3
diff -u -p -r1.3 xen_unified.h
--- src/xen_unified.h	30 Apr 2007 16:57:15 -0000	1.3
+++ src/xen_unified.h	26 Jun 2007 09:51:05 -0000
@@ -50,6 +50,9 @@ struct _xenUnifiedPrivate {
      * xen_unified.c.
      */
     int opened[XEN_UNIFIED_NR_DRIVERS];
+
+    /* Canonical URI. */
+    char *name;
 };
 
 typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.123
diff -u -p -r1.123 xend_internal.c
--- src/xend_internal.c	21 Jun 2007 15:49:09 -0000	1.123
+++ src/xend_internal.c	26 Jun 2007 09:51:07 -0000
@@ -73,6 +73,8 @@ virDriver xenDaemonDriver = {
     xenDaemonClose, /* close */
     xenDaemonGetType, /* type */
     xenDaemonGetVersion, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     NULL, /* getMaxVcpus */
     xenDaemonNodeGetInfo, /* nodeGetInfo */
     NULL, /* getCapabilities */
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.31
diff -u -p -r1.31 xm_internal.c
--- src/xm_internal.c	15 Jun 2007 15:24:20 -0000	1.31
+++ src/xm_internal.c	26 Jun 2007 09:51:08 -0000
@@ -81,6 +81,8 @@ virDriver xenXMDriver = {
     xenXMClose, /* close */
     xenXMGetType, /* type */
     NULL, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     NULL, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     NULL, /* getCapabilities */
Index: src/xs_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xs_internal.c,v
retrieving revision 1.43
diff -u -p -r1.43 xs_internal.c
--- src/xs_internal.c	5 Jun 2007 12:06:09 -0000	1.43
+++ src/xs_internal.c	26 Jun 2007 09:51:09 -0000
@@ -46,6 +46,8 @@ virDriver xenStoreDriver = {
     xenStoreClose, /* close */
     NULL, /* type */
     NULL, /* version */
+    NULL, /* hostname */
+    NULL, /* URI */
     NULL, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     NULL, /* getCapabilities */
