From 2be812bbc9f80e9f10a08c347673d08148c7f976 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 26 Jun 2007 11:42:46 +0000 Subject: [PATCH] Tue Jun 26 12:40:00 BST 2007 Richard W.M. Jones * include/libvirt/libvirt.h.in, src/libvirt.c: (and numerous other files) Added support for virConnectGetHostname and virConnectGetURI calls. --- ChangeLog | 6 +++ include/libvirt/libvirt.h | 4 ++ include/libvirt/libvirt.h.in | 4 ++ qemud/remote.c | 16 +++++++ qemud/remote_dispatch_localvars.h | 1 + qemud/remote_dispatch_proc_switch.h | 6 +++ qemud/remote_dispatch_prototypes.h | 1 + qemud/remote_protocol.c | 9 ++++ qemud/remote_protocol.h | 8 ++++ qemud/remote_protocol.x | 7 +++- src/driver.h | 6 +++ src/internal.h | 2 + src/libvirt.c | 57 +++++++++++++++++++++++++ src/libvirt_sym.version | 2 + src/proxy_internal.c | 2 + src/qemu_internal.c | 20 ++++++--- src/remote_internal.c | 65 ++++++++++++++++++++++++++--- src/test.c | 49 +++++++++++++++++++++- src/virsh.c | 62 ++++++++++++++++++++++++++- src/xen_internal.c | 2 + src/xen_unified.c | 55 +++++++++++++++++++++++- src/xen_unified.h | 3 ++ src/xend_internal.c | 2 + src/xm_internal.c | 2 + src/xs_internal.c | 2 + 25 files changed, 378 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 426ca509cd..cbc76d2b79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Jun 26 12:40:00 BST 2007 Richard W.M. Jones + + * include/libvirt/libvirt.h.in, src/libvirt.c: (and numerous + other files) Added support for virConnectGetHostname + and virConnectGetURI calls. + Mon Jun 25 16:55:00 BST 2007 Richard W.M. Jones * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_sym.version, diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index f733541366..3995c4bab2 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -272,6 +272,10 @@ int virConnectClose (virConnectPtr conn); 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. */ diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 9f5e070999..9f332e44e6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -272,6 +272,10 @@ int virConnectClose (virConnectPtr conn); 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. */ diff --git a/qemud/remote.c b/qemud/remote.c index f204326bb9..e53e883e5d 100644 --- a/qemud/remote.c +++ b/qemud/remote.c @@ -459,6 +459,22 @@ remoteDispatchGetVersion (struct qemud_client *client, return 0; } +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, diff --git a/qemud/remote_dispatch_localvars.h b/qemud/remote_dispatch_localvars.h index a7a00e7275..f782cfd6e2 100644 --- a/qemud/remote_dispatch_localvars.h +++ b/qemud/remote_dispatch_localvars.h @@ -20,6 +20,7 @@ remote_domain_get_os_type_ret lv_remote_domain_get_os_type_ret; remote_domain_get_autostart_args lv_remote_domain_get_autostart_args; remote_domain_get_autostart_ret lv_remote_domain_get_autostart_ret; remote_domain_set_vcpus_args lv_remote_domain_set_vcpus_args; +remote_get_hostname_ret lv_remote_get_hostname_ret; remote_domain_get_scheduler_type_args lv_remote_domain_get_scheduler_type_args; remote_domain_get_scheduler_type_ret lv_remote_domain_get_scheduler_type_ret; remote_network_undefine_args lv_remote_network_undefine_args; diff --git a/qemud/remote_dispatch_proc_switch.h b/qemud/remote_dispatch_proc_switch.h index e00c897357..b501d2c770 100644 --- a/qemud/remote_dispatch_proc_switch.h +++ b/qemud/remote_dispatch_proc_switch.h @@ -245,6 +245,12 @@ case REMOTE_PROC_GET_CAPABILITIES: ret = (char *) &lv_remote_get_capabilities_ret; memset (&lv_remote_get_capabilities_ret, 0, sizeof lv_remote_get_capabilities_ret); break; +case REMOTE_PROC_GET_HOSTNAME: + fn = (dispatch_fn) remoteDispatchGetHostname; + ret_filter = (xdrproc_t) xdr_remote_get_hostname_ret; + ret = (char *) &lv_remote_get_hostname_ret; + memset (&lv_remote_get_hostname_ret, 0, sizeof lv_remote_get_hostname_ret); + break; case REMOTE_PROC_GET_MAX_VCPUS: fn = (dispatch_fn) remoteDispatchGetMaxVcpus; args_filter = (xdrproc_t) xdr_remote_get_max_vcpus_args; diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h index 67e01d76ce..05344f6351 100644 --- a/qemud/remote_dispatch_prototypes.h +++ b/qemud/remote_dispatch_prototypes.h @@ -36,6 +36,7 @@ static int remoteDispatchDomainShutdown (struct qemud_client *client, remote_mes static int remoteDispatchDomainSuspend (struct qemud_client *client, remote_message_header *req, remote_domain_suspend_args *args, void *ret); static int remoteDispatchDomainUndefine (struct qemud_client *client, remote_message_header *req, remote_domain_undefine_args *args, void *ret); static int remoteDispatchGetCapabilities (struct qemud_client *client, remote_message_header *req, void *args, remote_get_capabilities_ret *ret); +static int remoteDispatchGetHostname (struct qemud_client *client, remote_message_header *req, void *args, remote_get_hostname_ret *ret); static int remoteDispatchGetMaxVcpus (struct qemud_client *client, remote_message_header *req, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret); static int remoteDispatchGetType (struct qemud_client *client, remote_message_header *req, void *args, remote_get_type_ret *ret); static int remoteDispatchGetVersion (struct qemud_client *client, remote_message_header *req, void *args, remote_get_version_ret *ret); diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c index ddbf345139..aa33507530 100644 --- a/qemud/remote_protocol.c +++ b/qemud/remote_protocol.c @@ -195,6 +195,15 @@ xdr_remote_get_version_ret (XDR *xdrs, remote_get_version_ret *objp) return TRUE; } +bool_t +xdr_remote_get_hostname_ret (XDR *xdrs, remote_get_hostname_ret *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->hostname)) + return FALSE; + return TRUE; +} + bool_t xdr_remote_get_max_vcpus_args (XDR *xdrs, remote_get_max_vcpus_args *objp) { diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h index ee3d1b0981..51376143cf 100644 --- a/qemud/remote_protocol.h +++ b/qemud/remote_protocol.h @@ -105,6 +105,11 @@ struct remote_get_version_ret { }; typedef struct remote_get_version_ret remote_get_version_ret; +struct remote_get_hostname_ret { + remote_nonnull_string hostname; +}; +typedef struct remote_get_hostname_ret remote_get_hostname_ret; + struct remote_get_max_vcpus_args { remote_string type; }; @@ -626,6 +631,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE = 56, REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, + REMOTE_PROC_GET_HOSTNAME = 59, }; typedef enum remote_procedure remote_procedure; @@ -669,6 +675,7 @@ extern bool_t xdr_remote_sched_param (XDR *, remote_sched_param*); extern bool_t xdr_remote_open_args (XDR *, remote_open_args*); extern bool_t xdr_remote_get_type_ret (XDR *, remote_get_type_ret*); extern bool_t xdr_remote_get_version_ret (XDR *, remote_get_version_ret*); +extern bool_t xdr_remote_get_hostname_ret (XDR *, remote_get_hostname_ret*); extern bool_t xdr_remote_get_max_vcpus_args (XDR *, remote_get_max_vcpus_args*); extern bool_t xdr_remote_get_max_vcpus_ret (XDR *, remote_get_max_vcpus_ret*); extern bool_t xdr_remote_node_get_info_ret (XDR *, remote_node_get_info_ret*); @@ -769,6 +776,7 @@ extern bool_t xdr_remote_sched_param (); extern bool_t xdr_remote_open_args (); extern bool_t xdr_remote_get_type_ret (); extern bool_t xdr_remote_get_version_ret (); +extern bool_t xdr_remote_get_hostname_ret (); extern bool_t xdr_remote_get_max_vcpus_args (); extern bool_t xdr_remote_get_max_vcpus_ret (); extern bool_t xdr_remote_node_get_info_ret (); diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x index 6343f7aebb..4470f557cf 100644 --- a/qemud/remote_protocol.x +++ b/qemud/remote_protocol.x @@ -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. */ diff --git a/src/driver.h b/src/driver.h index e3ed93b32b..077a4b4a4b 100644 --- a/src/driver.h +++ b/src/driver.h @@ -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; diff --git a/src/internal.h b/src/internal.h index 51f5349d78..a0a074de52 100644 --- a/src/internal.h +++ b/src/internal.h @@ -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: diff --git a/src/libvirt.c b/src/libvirt.c index f50c91926f..e473e533bf 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -465,6 +465,63 @@ virConnectGetVersion(virConnectPtr conn, unsigned long *hvVer) return -1; } +/** + * 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 diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version index 9b9f189542..01441491e7 100644 --- a/src/libvirt_sym.version +++ b/src/libvirt_sym.version @@ -6,6 +6,8 @@ virConnectClose; virConnectGetType; virConnectGetVersion; + virConnectGetHostname; + virConnectGetURI; virDomainGetConnect; virConnectListDomains; virConnectNumOfDomains; diff --git a/src/proxy_internal.c b/src/proxy_internal.c index 7f2ed69d9f..eca93176d2 100644 --- a/src/proxy_internal.c +++ b/src/proxy_internal.c @@ -53,6 +53,8 @@ virDriver xenProxyDriver = { xenProxyClose, /* close */ NULL, /* type */ xenProxyGetVersion, /* version */ + NULL, /* hostname */ + NULL, /* URI */ NULL, /* getMaxVcpus */ xenProxyNodeGetInfo, /* nodeGetInfo */ xenProxyGetCapabilities, /* getCapabilities */ diff --git a/src/qemu_internal.c b/src/qemu_internal.c index 644e2b09b8..367f71eb41 100644 --- a/src/qemu_internal.c +++ b/src/qemu_internal.c @@ -1023,13 +1023,16 @@ static int qemuNetworkOpen(virConnectPtr conn, 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 conn, static int qemuNetworkClose (virConnectPtr conn) { - qemuNetworkPrivatePtr netpriv = (qemuNetworkPrivatePtr) conn->networkPrivateData; + if (STRNEQ (conn->driver->name, "remote")) { + qemuNetworkPrivatePtr netpriv = + (qemuNetworkPrivatePtr) conn->networkPrivateData; - if (!netpriv->shared) - close(netpriv->qemud_fd); - free(netpriv); - conn->networkPrivateData = NULL; + 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 */ diff --git a/src/remote_internal.c b/src/remote_internal.c index 21bc0631f7..31db7a1a80 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -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 char *uri_str, int flags) 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 char *uri_str, int flags) 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, unsigned long *hvVer) 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, diff --git a/src/test.c b/src/test.c index 723d7e7ad8..2a1cc58ba2 100644 --- a/src/test.c +++ b/src/test.c @@ -22,9 +22,13 @@ */ #ifdef WITH_TEST + +#define _GNU_SOURCE /* for asprintf */ + #include #include #include +#include #include #include #include @@ -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 ATTRIBUTE_UNUSED, 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) { diff --git a/src/virsh.c b/src/virsh.c index 0362bf7892..9e837beaf5 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -2588,7 +2588,65 @@ cmdVersion(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED) } /* - * "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 "}, @@ -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}, diff --git a/src/xen_internal.c b/src/xen_internal.c index 36c1374cf9..75a6c4d43d 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -597,6 +597,8 @@ virDriver xenHypervisorDriver = { xenHypervisorClose, /* close */ xenHypervisorGetType, /* type */ xenHypervisorGetVersion, /* version */ + NULL, /* hostname */ + NULL, /* URI */ xenHypervisorGetMaxVcpus, /* getMaxVcpus */ NULL, /* nodeGetInfo */ xenHypervisorGetCapabilities, /* getCapabilities */ diff --git a/src/xen_unified.c b/src/xen_unified.c index cc10a4fe5e..ba1e7606fe 100644 --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -129,13 +130,20 @@ xenUnifiedOpen (virConnectPtr conn, const char *name, int flags) 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, const char *name, int flags) 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, unsigned long *hvVer) 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, diff --git a/src/xen_unified.h b/src/xen_unified.h index 815722b03d..f17ec5cbd3 100644 --- a/src/xen_unified.h +++ b/src/xen_unified.h @@ -50,6 +50,9 @@ struct _xenUnifiedPrivate { * xen_unified.c. */ int opened[XEN_UNIFIED_NR_DRIVERS]; + + /* Canonical URI. */ + char *name; }; typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr; diff --git a/src/xend_internal.c b/src/xend_internal.c index 7885484be1..27abafa03f 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -73,6 +73,8 @@ virDriver xenDaemonDriver = { xenDaemonClose, /* close */ xenDaemonGetType, /* type */ xenDaemonGetVersion, /* version */ + NULL, /* hostname */ + NULL, /* URI */ NULL, /* getMaxVcpus */ xenDaemonNodeGetInfo, /* nodeGetInfo */ NULL, /* getCapabilities */ diff --git a/src/xm_internal.c b/src/xm_internal.c index e44fd2232e..04fd6611a7 100644 --- a/src/xm_internal.c +++ b/src/xm_internal.c @@ -81,6 +81,8 @@ virDriver xenXMDriver = { xenXMClose, /* close */ xenXMGetType, /* type */ NULL, /* version */ + NULL, /* hostname */ + NULL, /* URI */ NULL, /* getMaxVcpus */ NULL, /* nodeGetInfo */ NULL, /* getCapabilities */ diff --git a/src/xs_internal.c b/src/xs_internal.c index ace3ee0a27..264959cb13 100644 --- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -46,6 +46,8 @@ virDriver xenStoreDriver = { xenStoreClose, /* close */ NULL, /* type */ NULL, /* version */ + NULL, /* hostname */ + NULL, /* URI */ NULL, /* getMaxVcpus */ NULL, /* nodeGetInfo */ NULL, /* getCapabilities */ -- 2.47.2