admin: Add URI support and introduce virAdmGetDefaultURI

Since virt-admin should be able to connect to various admin servers
on hosted different daemons, we need to provide URI support to
libvirt-admin.
This commit is contained in:
Erik Skultety 2015-10-12 16:07:52 +02:00
parent 0ecf9b3e09
commit dbecb87f94
7 changed files with 142 additions and 33 deletions

View File

@ -59,6 +59,7 @@ int virAdmConnectIsAlive(virAdmConnectPtr conn);
int virAdmGetVersion(unsigned long long *libVer);
char *virAdmConnectGetURI(virAdmConnectPtr conn);
# ifdef __cplusplus
}

View File

@ -832,4 +832,6 @@ virAdmConnectDispose(void *obj)
if (conn->privateDataFreeFunc)
conn->privateDataFreeFunc(conn);
virURIFree(conn->uri);
}

View File

@ -397,6 +397,7 @@ struct _virConnect {
*/
struct _virAdmConnect {
virObjectLockable object;
virURIPtr uri;
void *privateData;
virFreeCallback privateDataFreeFunc;

View File

@ -27,6 +27,7 @@
#include "configmake.h"
#include "viralloc.h"
#include "virconf.h"
#include "virlog.h"
#include "virnetclient.h"
#include "virobject.h"
@ -95,60 +96,54 @@ virAdmInitialize(void)
}
static char *
getSocketPath(const char *name)
getSocketPath(virURIPtr uri)
{
char *rundir = virGetUserRuntimeDirectory();
char *sock_path = NULL;
size_t i = 0;
virURIPtr uri = NULL;
if (name) {
if (!(uri = virURIParse(name)))
goto error;
if (!uri)
goto cleanup;
if (STRNEQ(uri->scheme, "admin") ||
uri->server || uri->user || uri->fragment) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid connection name '%s'"), name);
goto error;
}
for (i = 0; i < uri->paramsCount; i++) {
virURIParamPtr param = &uri->params[i];
for (i = 0; i < uri->paramsCount; i++) {
virURIParamPtr param = &uri->params[i];
if (STREQ(param->name, "socket")) {
VIR_FREE(sock_path);
if (VIR_STRDUP(sock_path, param->value) < 0)
goto error;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unknown URI parameter '%s'"), param->name);
if (STREQ(param->name, "socket")) {
VIR_FREE(sock_path);
if (VIR_STRDUP(sock_path, param->value) < 0)
goto error;
}
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unknown URI parameter '%s'"), param->name);
goto error;
}
}
if (!sock_path) {
if (!uri || !uri->path || STREQ(uri->path, "/system")) {
if (STRNEQ(uri->scheme, "libvirtd")) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported URI scheme '%s'"),
uri->scheme);
goto error;
}
if (STREQ_NULLABLE(uri->path, "/system")) {
if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0)
goto error;
} else if (STREQ_NULLABLE(uri->path, "/session")) {
if (!rundir)
goto error;
if (virAsprintf(&sock_path,
"%s%s", rundir, LIBVIRTD_ADMIN_SOCK_NAME) < 0)
if (!rundir || virAsprintf(&sock_path, "%s%s", rundir,
LIBVIRTD_ADMIN_SOCK_NAME) < 0)
goto error;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid URI path '%s'"), uri->path);
_("Invalid URI path '%s', try '/system'"),
uri->path ? uri->path : "");
goto error;
}
}
cleanup:
VIR_FREE(rundir);
virURIFree(uri);
return sock_path;
error:
@ -156,6 +151,37 @@ getSocketPath(const char *name)
goto cleanup;
}
static const char *
virAdmGetDefaultURI(virConfPtr conf)
{
virConfValuePtr value = NULL;
const char *uristr = NULL;
uristr = virGetEnvAllowSUID("LIBVIRT_ADMIN_DEFAULT_URI");
if (uristr && *uristr) {
VIR_DEBUG("Using LIBVIRT_ADMIN_DEFAULT_URI '%s'", uristr);
} else if ((value = virConfGetValue(conf, "admin_uri_default"))) {
if (value->type != VIR_CONF_STRING) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Expected a string for 'admin_uri_default' config "
"parameter"));
return NULL;
}
VIR_DEBUG("Using config file uri '%s'", value->str);
uristr = value->str;
} else {
/* Since we can't probe connecting via any hypervisor driver as libvirt
* does, if no explicit URI was given and neither the environment
* variable, nor the configuration parameter had previously been set,
* we set the default admin server URI to 'libvirtd://system'.
*/
uristr = "libvirtd:///system";
}
return uristr;
}
/**
* virAdmConnectOpen:
* @name: uri of the daemon to connect to, NULL for default
@ -170,6 +196,7 @@ virAdmConnectOpen(const char *name, unsigned int flags)
{
char *sock_path = NULL;
virAdmConnectPtr conn = NULL;
virConfPtr conf = NULL;
if (virAdmInitialize() < 0)
goto error;
@ -180,7 +207,16 @@ virAdmConnectOpen(const char *name, unsigned int flags)
if (!(conn = virAdmConnectNew()))
goto error;
if (!(sock_path = getSocketPath(name)))
if (virConfLoadConfig(&conf, "libvirt-admin.conf") < 0)
goto error;
if (!name && !(name = virAdmGetDefaultURI(conf)))
goto error;
if (!(conn->uri = virURIParse(name)))
goto error;
if (!(sock_path = getSocketPath(conn->uri)))
goto error;
if (!(conn->privateData = remoteAdminPrivNew(sock_path)))
@ -193,6 +229,7 @@ virAdmConnectOpen(const char *name, unsigned int flags)
cleanup:
VIR_FREE(sock_path);
virConfFree(conf);
return conn;
error:
@ -340,3 +377,30 @@ virAdmConnectIsAlive(virAdmConnectPtr conn)
return ret;
}
/**
* virAdmConnectGetURI:
* @conn: pointer to an admin connection
*
* String returned by this method is normally the same as the string passed
* to the virAdmConnectOpen. Even if NULL was passed to virAdmConnectOpen,
* this method returns a non-null URI string.
*
* Returns an URI string related to the connection or NULL in case of an error.
* Caller is responsible for freeing the string.
*/
char *
virAdmConnectGetURI(virAdmConnectPtr conn)
{
char *uri = NULL;
VIR_DEBUG("conn=%p", conn);
virResetLastError();
virCheckAdmConnectReturn(conn, NULL);
if (!(uri = virURIFormat(conn->uri)))
virDispatchError(NULL);
return uri;
}

View File

@ -12,7 +12,8 @@
#]
#
# This can be used to prevent probing of the hypervisor
# driver when no URI is supplied by the application.
# These can be used in cases when no URI is supplied by the application
# (@uri_default also prevents probing of the hypervisor driver).
#
#uri_default = "qemu:///system"
#uri_default_admin = "libvirtd:///system"

View File

@ -17,4 +17,5 @@ LIBVIRT_ADMIN_1.3.0 {
virAdmConnectRef;
virAdmGetVersion;
virAdmConnectIsAlive;
virAdmConnectGetURI;
};

View File

@ -113,6 +113,39 @@ vshAdmReconnect(vshControl *ctl)
priv->wantReconnect = false;
}
/*
* 'uri' command
*/
static const vshCmdInfo info_uri[] = {
{.name = "help",
.data = N_("print the admin server URI")
},
{.name = "desc",
.data = ""
},
{.name = NULL}
};
static bool
cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *uri;
vshAdmControlPtr priv = ctl->privData;
uri = virAdmConnectGetURI(priv->conn);
if (!uri) {
vshError(ctl, "%s", _("failed to get URI"));
return false;
}
vshPrint(ctl, "%s\n", uri);
VIR_FREE(uri);
return true;
}
/* ---------------
* Command Connect
* ---------------
@ -425,6 +458,12 @@ static const vshCmdDef vshAdmCmds[] = {
VSH_CMD_HELP,
VSH_CMD_PWD,
VSH_CMD_QUIT,
{.name = "uri",
.handler = cmdURI,
.opts = NULL,
.info = info_uri,
.flags = 0
},
{.name = "connect",
.handler = cmdConnect,
.opts = opts_connect,