admin: Introduce adminDaemonConnectListServers API

This API is merely a convenience API, i.e. when managing clients connected to
daemon's servers, we should know (convenience) which server the specific client
is connected to. This implies a client-side representation of a server along
with a basic API to let the administrating client know what servers are actually
available on the daemon.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Erik Skultety 2015-08-14 09:17:01 +02:00
parent c50a834b80
commit 1a07c2efb3
14 changed files with 396 additions and 4 deletions

View File

@ -128,7 +128,7 @@ libvirtd_conf_la_LIBADD = $(LIBXML_LIBS)
noinst_LTLIBRARIES += libvirtd_admin.la
libvirtd_admin_la_SOURCES = \
admin.c admin.h
admin.c admin.h admin_server.c admin_server.h
libvirtd_admin_la_CFLAGS = \
$(AM_CFLAGS) \

View File

@ -28,6 +28,7 @@
#include "admin_protocol.h"
#include "admin.h"
#include "admin_server.h"
#include "datatypes.h"
#include "viralloc.h"
#include "virerror.h"
@ -77,6 +78,15 @@ remoteAdmClientInitHook(virNetServerClientPtr client ATTRIBUTE_UNUSED,
return priv;
}
/* Helpers */
static void
make_nonnull_server(admin_nonnull_server *srv_dst,
virAdmServerPtr srv_src)
{
ignore_value(VIR_STRDUP_QUIET(srv_dst->name, srv_src->name));
}
/* Functions */
static int
adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
@ -123,4 +133,49 @@ adminConnectGetLibVersion(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
return 0;
}
static int
adminDispatchConnectListServers(virNetServerPtr server ATTRIBUTE_UNUSED,
virNetServerClientPtr client,
virNetMessagePtr msg ATTRIBUTE_UNUSED,
virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
admin_connect_list_servers_args *args,
admin_connect_list_servers_ret *ret)
{
virAdmServerPtr *servers = NULL;
int nservers = 0;
int rv = -1;
size_t i;
struct daemonAdmClientPrivate *priv =
virNetServerClientGetPrivateData(client);
if ((nservers =
adminDaemonListServers(priv->dmn,
args->need_results ? &servers : NULL,
args->flags)) < 0)
goto cleanup;
if (servers && nservers) {
if (VIR_ALLOC_N(ret->servers.servers_val, nservers) < 0)
goto cleanup;
ret->servers.servers_len = nservers;
for (i = 0; i < nservers; i++)
make_nonnull_server(ret->servers.servers_val + i, servers[i]);
} else {
ret->servers.servers_len = 0;
ret->servers.servers_val = NULL;
}
ret->ret = nservers;
rv = 0;
cleanup:
if (rv < 0)
virNetMessageSaveError(rerr);
if (servers && nservers > 0)
for (i = 0; i < nservers; i++)
virObjectUnref(servers[i]);
VIR_FREE(servers);
return rv;
}
#include "admin_dispatch.h"

73
daemon/admin_server.c Normal file
View File

@ -0,0 +1,73 @@
/*
* admin_server.c: admin methods to manage daemons and clients
*
* Copyright (C) 2016 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
* Authors: Erik Skultety <eskultet@redhat.com>
* Martin Kletzander <mkletzan@redhat.com>
*/
#include <config.h>
#include "admin_server.h"
#include "datatypes.h"
#include "viralloc.h"
#include "virerror.h"
#include "virlog.h"
#include "virnetdaemon.h"
#include "virnetserver.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_ADMIN
VIR_LOG_INIT("daemon.admin_server");
int
adminDaemonListServers(virNetDaemonPtr dmn,
virAdmServerPtr **servers,
unsigned int flags)
{
int ret = -1;
const char **srv_names = NULL;
virAdmServerPtr *srvs = NULL;
size_t i;
ssize_t nsrvs = 0;
virCheckFlags(0, -1);
if ((nsrvs = virNetDaemonGetServerNames(dmn, &srv_names)) < 0)
goto cleanup;
if (servers) {
if (VIR_ALLOC_N(srvs, nsrvs) < 0)
goto cleanup;
for (i = 0; i < nsrvs; i++) {
if (!(srvs[i] = virAdmGetServer(NULL, srv_names[i])))
goto cleanup;
}
*servers = srvs;
srvs = NULL;
}
ret = nsrvs;
cleanup:
virObjectListFree(srvs);
return ret;
}

34
daemon/admin_server.h Normal file
View File

@ -0,0 +1,34 @@
/*
* admin_server.h: admin methods to manage daemons and clients
*
* Copyright (C) 2016 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
* Authors: Erik Skultety <eskultet@redhat.com>
* Martin Kletzander <mkletzan@redhat.com>
*/
#ifndef __LIBVIRTD_ADMIN_SERVER_H__
# define __LIBVIRTD_ADMIN_SERVER_H__
# include "rpc/virnetdaemon.h"
int
adminDaemonListServers(virNetDaemonPtr dmn,
virAdmServerPtr **servers,
unsigned int flags);
#endif /* __LIBVIRTD_ADMIN_SERVER_H__ */

View File

@ -70,9 +70,13 @@ typedef virAdmServer *virAdmServerPtr;
virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags);
int virAdmConnectClose(virAdmConnectPtr conn);
int virAdmConnectRef(virAdmConnectPtr conn);
int virAdmConnectIsAlive(virAdmConnectPtr conn);
int virAdmServerFree(virAdmServerPtr srv);
int virAdmConnectListServers(virAdmConnectPtr dmn,
virAdmServerPtr **servers,
unsigned int flags);
int virAdmGetVersion(unsigned long long *libVer);
@ -100,6 +104,8 @@ int virAdmConnectRegisterCloseCallback(virAdmConnectPtr conn,
int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
virAdmConnectCloseFunc cb);
const char *virAdmServerGetName(virAdmServerPtr srv);
# ifdef __cplusplus
}
# endif

View File

@ -10,6 +10,7 @@ gnulib/lib/gai_strerror.c
gnulib/lib/regcomp.c
src/access/viraccessdriverpolkit.c
src/access/viraccessmanager.c
src/admin/admin_remote.c
src/bhyve/bhyve_command.c
src/bhyve/bhyve_device.c
src/bhyve/bhyve_driver.c

View File

@ -55,6 +55,16 @@ struct admin_connect_get_lib_version_ret {
unsigned hyper libVer;
};
struct admin_connect_list_servers_args {
unsigned int need_results;
unsigned int flags;
};
struct admin_connect_list_servers_ret {
admin_nonnull_server servers<ADMIN_SERVER_LIST_MAX>;
unsigned int ret;
};
/* Define the program number, protocol version and procedure numbers here. */
const ADMIN_PROGRAM = 0x06900690;
const ADMIN_PROTOCOL_VERSION = 1;
@ -90,5 +100,11 @@ enum admin_procedure {
/**
* @generate: both
*/
ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3
ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3,
/**
* @generate: none
* @priority: high
*/
ADMIN_PROC_CONNECT_LIST_SERVERS = 4
};

View File

@ -47,6 +47,14 @@ remoteAdminPrivDispose(void *opaque)
}
/* Helpers */
static virAdmServerPtr
get_nonnull_server(virAdmConnectPtr conn, admin_nonnull_server server)
{
return virAdmGetServer(conn, server.name);
}
static int
callFull(virAdmConnectPtr conn ATTRIBUTE_UNUSED,
remoteAdminPrivPtr priv,
@ -214,3 +222,66 @@ remoteAdminPrivNew(const char *sock_path)
virObjectUnref(priv);
return NULL;
}
static int
remoteAdminConnectListServers(virAdmConnectPtr conn,
virAdmServerPtr **servers,
unsigned int flags)
{
int rv = -1;
size_t i;
virAdmServerPtr *tmp_srvs = NULL;
remoteAdminPrivPtr priv = conn->privateData;
admin_connect_list_servers_args args;
admin_connect_list_servers_ret ret;
args.need_results = !!servers;
args.flags = flags;
memset(&ret, 0, sizeof(ret));
virObjectLock(priv);
if (call(conn,
0,
ADMIN_PROC_CONNECT_LIST_SERVERS,
(xdrproc_t) xdr_admin_connect_list_servers_args,
(char *) &args,
(xdrproc_t) xdr_admin_connect_list_servers_ret,
(char *) &ret) == -1)
goto done;
if (ret.servers.servers_len > ADMIN_SERVER_LIST_MAX) {
virReportError(VIR_ERR_RPC,
_("Too many servers '%d' for limit '%d'"),
ret.servers.servers_len, ADMIN_SERVER_LIST_MAX);
goto cleanup;
}
if (servers) {
if (VIR_ALLOC_N(tmp_srvs, ret.servers.servers_len + 1) < 0)
goto cleanup;
for (i = 0; i < ret.servers.servers_len; i++) {
tmp_srvs[i] = get_nonnull_server(conn, ret.servers.servers_val[i]);
if (!tmp_srvs[i])
goto cleanup;
}
*servers = tmp_srvs;
tmp_srvs = NULL;
}
rv = ret.ret;
cleanup:
if (tmp_srvs) {
for (i = 0; i < ret.servers.servers_len; i++)
virObjectUnref(tmp_srvs[i]);
VIR_FREE(tmp_srvs);
}
xdr_free((xdrproc_t) xdr_admin_connect_list_servers_ret, (char *) &ret);
done:
virObjectUnlock(priv);
return rv;
}

View File

@ -8,8 +8,20 @@ struct admin_connect_open_args {
struct admin_connect_get_lib_version_ret {
uint64_t libVer;
};
struct admin_connect_list_servers_args {
u_int need_results;
u_int flags;
};
struct admin_connect_list_servers_ret {
struct {
u_int servers_len;
admin_nonnull_server * servers_val;
} servers;
u_int ret;
};
enum admin_procedure {
ADMIN_PROC_CONNECT_OPEN = 1,
ADMIN_PROC_CONNECT_CLOSE = 2,
ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3,
ADMIN_PROC_CONNECT_LIST_SERVERS = 4,
};

View File

@ -549,7 +549,86 @@ int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
goto error;
return 0;
error:
virDispatchError(NULL);
return -1;
}
/**
* virAdmServerGetName:
* @srv: a server object
*
* Get the public name for specified server
*
* Returns a pointer to the name or NULL. The string doesn't need to be
* deallocated since its lifetime will be the same as the server object.
*/
const char *
virAdmServerGetName(virAdmServerPtr srv)
{
VIR_DEBUG("server=%p", srv);
virResetLastError();
virCheckAdmServerReturn(srv, NULL);
return srv->name;
}
/**
* virAdmServerFree:
* @srv: server object
*
* Release the server object. The running instance is kept alive.
* The data structure is freed and should not be used thereafter.
*
* Returns 0 on success, -1 on failure.
*/
int virAdmServerFree(virAdmServerPtr srv)
{
VIR_DEBUG("server=%p", srv);
virResetLastError();
virCheckAdmServerReturn(srv, -1);
virObjectUnref(srv);
return 0;
}
/**
* virAdmConnectListServers:
* @conn: daemon connection reference
* @servers: Pointer to a list to store an array containing objects or NULL
* if the list is not required (number of servers only)
* @flags: bitwise-OR of virAdmConnectListServersFlags
*
* Collect list of all servers provided by daemon the client is connected to.
*
* Returns the number of servers available on daemon side or -1 in case of a
* failure, setting @servers to NULL. There is a guaranteed extra element set
* to NULL in the @servers list returned to make the iteration easier, excluding
* this extra element from the final count.
* Caller is responsible to call virAdmServerFree() on each list element,
* followed by freeing @servers.
*/
int
virAdmConnectListServers(virAdmConnectPtr conn,
virAdmServerPtr **servers,
unsigned int flags)
{
int ret = -1;
VIR_DEBUG("conn=%p, servers=%p, flags=%x", conn, servers, flags);
virResetLastError();
if (servers)
*servers = NULL;
virCheckAdmConnectReturn(conn, -1);
if ((ret = remoteAdminConnectListServers(conn, servers, flags)) < 0)
goto error;
return ret;
error:
virDispatchError(NULL);
return -1;

View File

@ -7,6 +7,8 @@
# admin/admin_protocol.x
xdr_admin_connect_get_lib_version_ret;
xdr_admin_connect_list_servers_args;
xdr_admin_connect_list_servers_ret;
xdr_admin_connect_open_args;
# datatypes.h

View File

@ -21,4 +21,7 @@ LIBVIRT_ADMIN_1.3.0 {
virAdmConnectGetLibVersion;
virAdmConnectRegisterCloseCallback;
virAdmConnectUnregisterCloseCallback;
virAdmConnectListServers;
virAdmServerGetName;
virAdmServerFree;
};

View File

@ -190,6 +190,45 @@ virNetDaemonGetServer(virNetDaemonPtr dmn,
return srv;
}
/*
* Returns number of names allocated in *servers, on error sets
* *servers to NULL and returns -1. List of *servers must be free()d,
* but not the items in it (similarly to virHashGetItems).
*/
ssize_t
virNetDaemonGetServerNames(virNetDaemonPtr dmn,
const char ***servers)
{
virHashKeyValuePairPtr items = NULL;
size_t nservers = 0;
ssize_t ret = -1;
size_t i;
*servers = NULL;
virObjectLock(dmn);
items = virHashGetItems(dmn->servers, NULL);
if (!items)
goto cleanup;
for (i = 0; items[i].key; i++) {
if (VIR_APPEND_ELEMENT(*servers, nservers, items[i].key) < 0)
goto cleanup;
}
ret = nservers;
cleanup:
if (ret < 0)
VIR_FREE(*servers);
VIR_FREE(items);
virObjectUnlock(dmn);
return ret;
}
virNetServerPtr
virNetDaemonAddServerPostExec(virNetDaemonPtr dmn,
const char *serverName,

View File

@ -83,5 +83,6 @@ bool virNetDaemonHasClients(virNetDaemonPtr dmn);
virNetServerPtr virNetDaemonGetServer(virNetDaemonPtr dmn,
const char *serverName);
ssize_t virNetDaemonGetServerNames(virNetDaemonPtr dmn, const char ***servers);
#endif /* __VIR_NET_DAEMON_H__ */