This is the first API to the admin interface. This particular API is
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.
---
daemon/Makefile.am | 2 +-
daemon/admin.c | 57 ++++++++++++++
daemon/admin_server.c | 82 +++++++++++++++++++
daemon/admin_server.h | 33 ++++++++
include/libvirt/libvirt-admin.h | 8 ++
src/admin/admin_protocol.x | 18 ++++-
src/admin_protocol-structs | 16 ++++
src/libvirt-admin.c | 171 ++++++++++++++++++++++++++++++++++++++++
src/libvirt_admin_public.syms | 4 +
src/rpc/virnetdaemon.c | 14 ++++
src/rpc/virnetdaemon.h | 2 +
src/rpc/virnetserver.c | 24 ++++++
src/rpc/virnetserver.h | 3 +
13 files changed, 432 insertions(+), 2 deletions(-)
create mode 100644 daemon/admin_server.c
create mode 100644 daemon/admin_server.h
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5b13960..d255c89 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -129,7 +129,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) \
diff --git a/daemon/admin.c b/daemon/admin.c
index 53144ee..6c5b1a9 100644
--- a/daemon/admin.c
+++ b/daemon/admin.c
@@ -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,16 @@ remoteAdmClientInitHook(virNetServerClientPtr client ATTRIBUTE_UNUSED,
return priv;
}
+/* Helpers */
+
+static void
+make_nonnull_server(admin_nonnull_server *srv_dst,
+ virAdmServerPtr srv_src)
+{
+ srv_dst->id = srv_src->id;
+ ignore_value(VIR_STRDUP_QUIET(srv_dst->name, srv_src->name));
+}
+
/* Functions */
static int
adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
@@ -114,4 +125,50 @@ adminDispatchConnectClose(virNetServerPtr server 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 =
+ adminDaemonConnectListServers(priv->dmn,
The 'DaemonConnect' is unnecessary here. I would like the defaults
for admin api to be similar to the default API, but with few changes.
If something is called on virConnectPtr, it starts with virConnectPtr
and its first parameter is virConnectPtr on both client and server.
If something is called on virAdmConnectPtr, it would start with virAdm
and its first parameter would be virAdmConnectPtr on client, but
virNetDaemonPtr on server. I don't see the need for having the
virAdmConnectPtr on the server as a part of the API right now. And
it's internal, so we can change that later on.
Consequantly whe we add an admin API that does something with a
server, it will look like this. Let's say the function will be
listing clients. On client, it will be virAdmServerListClients(),
it's first parameter will be virAdmServerPtr, and on daemon it will be
adminServerListClients() and its first parameter will be
virNetServerPtr.
That said its visible that we will need to do some translation so that
the server part can deal with virNetServerPtr and directly even though
we only send the id (and name) over RPC. And that's what the helper
functions are for, the serialization and de-serialization or RPC
stuff. It's not applicable to the listing of servers, but I wanted to
mention it for later on, just so we're on the same page and can
prepare for the fact that gendispatch.pl will need some work done on
it :)
+ 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"
diff --git a/daemon/admin_server.c b/daemon/admin_server.c
new file mode 100644
index 0000000..9d55074
--- /dev/null
+++ b/daemon/admin_server.c
@@ -0,0 +1,82 @@
+/*
+ * admin_server.c: admin methods to manage daemons and clients
+ *
+ * Copyright (C) 2014-2015 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/>.
+ *
+ * Author: Martin Kletzander <mkletzan(a)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
+adminDaemonConnectListServers(virNetDaemonPtr dmn,
+ virAdmServerPtr **servers,
+ unsigned int flags)
+{
+ int ret = -1;
+ unsigned int id;
+ const char *name = NULL;
+ virNetServerPtr *srv_objs = NULL;
+ virAdmServerPtr *srvs = NULL;
+ size_t i;
+ size_t nsrvs = 0;
+
+ virCheckFlags(0, -1);
+
+ nsrvs = virNetDaemonGetServers(dmn, &srv_objs);
+ if (servers) {
+ if (VIR_ALLOC_N(srvs, nsrvs + 1) < 0)
+ goto cleanup;
+
+ for (i = 0; i < nsrvs; i++) {
+ virNetServerPtr srv = srv_objs[i];
+
+ name = virNetServerGetName(srv);
+ id = virNetServerGetID(srv);
+
+ virObjectLock(srv);
+ if (!(srvs[i] = virAdmGetServer(NULL, name, id))) {
+ virObjectUnlock(srv);
+ goto cleanup;
+ }
+
+ virObjectUnlock(srv);
+ }
+
+ *servers = srvs;
+ srvs = NULL;
+ }
+
+ ret = nsrvs;
+
+ cleanup:
+ virObjectListFree(srvs);
+ return ret;
+}
diff --git a/daemon/admin_server.h b/daemon/admin_server.h
new file mode 100644
index 0000000..aa8f060
--- /dev/null
+++ b/daemon/admin_server.h
@@ -0,0 +1,33 @@
+/*
+ * admin_server.h: admin methods to manage daemons and clients
+ *
+ * Copyright (C) 2015 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/>.
+ *
+ * Author: Martin Kletzander <mkletzan(a)redhat.com>
+ */
+
+#ifndef __LIBVIRTD_ADMIN_SERVER_H__
+# define __LIBVIRTD_ADMIN_SERVER_H__
+
+# include "rpc/virnetdaemon.h"
+
+int
+adminDaemonConnectListServers(virNetDaemonPtr dmn,
+ virAdmServerPtr **servers,
+ unsigned int flags);
+
+#endif /* __LIBVIRTD_ADMIN_SERVER_H__ */
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index f0752f5..83e73ca 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -55,8 +55,16 @@ typedef virAdmServer *virAdmServerPtr;
virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags);
int virAdmConnectClose(virAdmConnectPtr conn);
+int virAdmConnectListServers(virAdmConnectPtr conn,
+ virAdmServerPtr **servers,
+ unsigned int flags);
+
+int virAdmServerFree(virAdmServerPtr srv);
int virAdmConnectRef(virAdmConnectPtr conn);
+unsigned int virAdmGetServerID(virAdmServerPtr srv);
+const char *virAdmGetServerName(virAdmServerPtr srv);
+
# ifdef __cplusplus
}
# endif
diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x
index d062e9a..05b31ea 100644
--- a/src/admin/admin_protocol.x
+++ b/src/admin/admin_protocol.x
@@ -50,6 +50,16 @@ struct admin_connect_open_args {
unsigned int flags;
};
+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;
@@ -80,5 +90,11 @@ enum admin_procedure {
/**
* @generate: client
*/
- ADMIN_PROC_CONNECT_CLOSE = 2
+ ADMIN_PROC_CONNECT_CLOSE = 2,
+
+ /**
+ * @generate: none
+ * @priority: high
+ */
+ ADMIN_PROC_CONNECT_LIST_SERVERS = 3
};
diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs
index 3ac31fa..6fcd082 100644
--- a/src/admin_protocol-structs
+++ b/src/admin_protocol-structs
@@ -1,8 +1,24 @@
/* -*- c -*- */
+struct admin_nonnull_server {
+ admin_nonnull_string name;
+ uint64_t id;
+};
struct admin_connect_open_args {
u_int flags;
};
+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_LIST_SERVERS = 3,
};
diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c
index b3fd0b3..7067c92 100644
--- a/src/libvirt-admin.c
+++ b/src/libvirt-admin.c
@@ -123,6 +123,16 @@ call(virAdmConnectPtr conn,
#include "admin_protocol.h"
#include "admin_client.h"
+/* Helpers */
+static virAdmServerPtr
+get_nonnull_server(virAdmConnectPtr conn, admin_nonnull_server server)
+{
+ virAdmServerPtr srv;
+
+ srv = virAdmGetServer(conn, server.name, server.id);
+ return srv;
+}
+
static bool virAdmGlobalError;
static virOnceControl virAdmGlobalOnce = VIR_ONCE_CONTROL_INITIALIZER;
@@ -385,3 +395,164 @@ virAdmConnectRef(virAdmConnectPtr conn)
return 0;
}
+
+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));
+ 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;
+}
+
+
+/**
+ * virAdmGetServerID:
+ * @srv: a server object
+ *
+ * Get the server ID number.
+ *
+ * Returns the server ID number on success, (unsigned int) -1 on failure.
+ */
+unsigned int
+virAdmGetServerID(virAdmServerPtr srv)
+{
+ VIR_DEBUG("server=%p", srv);
+
+ virResetLastError();
+ virCheckAdmServerReturn(srv, (unsigned int)-1);
+
+ return srv->id;
+}
+
+/**
+ * virAdmGetServerName:
+ * @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 *
+virAdmGetServerName(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;
+}
diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms
index d9e3c0b..dbb5f76 100644
--- a/src/libvirt_admin_public.syms
+++ b/src/libvirt_admin_public.syms
@@ -15,4 +15,8 @@ LIBVIRT_ADMIN_1.3.0 {
virAdmConnectOpen;
virAdmConnectClose;
virAdmConnectRef;
+ virAdmConnectListServers;
+ virAdmGetServerID;
+ virAdmGetServerName;
+ virAdmServerFree;
};
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index a3dde4e..b2f902f 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -205,6 +205,20 @@ virNetDaemonGetServer(virNetDaemonPtr dmn,
return srv;
}
+size_t
+virNetDaemonGetServers(virNetDaemonPtr dmn,
+ virNetServerPtr **servers)
+{
+ size_t nservers;
+
+ virObjectLock(dmn);
+ nservers = dmn->nservers;
+ *servers = dmn->servers;
+ virObjectUnlock(dmn);
+
+ return nservers;
+}
+
static int
virNetDaemonAddServerPostExec(virNetDaemonPtr dmn,
virJSONValuePtr object,
diff --git a/src/rpc/virnetdaemon.h b/src/rpc/virnetdaemon.h
index 8ad799a..9450575 100644
--- a/src/rpc/virnetdaemon.h
+++ b/src/rpc/virnetdaemon.h
@@ -94,6 +94,8 @@ bool virNetDaemonHasClients(virNetDaemonPtr dmn);
virNetServerPtr virNetDaemonGetServer(virNetDaemonPtr dmn,
int subServerID);
+size_t virNetDaemonGetServers(virNetDaemonPtr dmn,
+ virNetServerPtr **servers);
void virNetDaemonRegisterFallbackData(virNetDaemonFallbackDataPtr data);
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index c0a205f..1ecad79 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -835,6 +835,30 @@ virNetServerHasClients(virNetServerPtr srv)
return ret;
}
+const char *
+virNetServerGetName(virNetServerPtr srv)
+{
+ const char *name;
+
+ virObjectLock(srv);
+ name = srv->name;
+ virObjectUnlock(srv);
+
+ return name;
+}
+
+unsigned int
+virNetServerGetID(virNetServerPtr srv)
+{
+ unsigned int id;
+
+ virObjectLock(srv);
+ id = srv->id;
+ virObjectUnlock(srv);
+
+ return id;
+}
+
void
virNetServerProcessClients(virNetServerPtr srv)
{
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 96137cc..d572650 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -87,4 +87,7 @@ void virNetServerUpdateServices(virNetServerPtr srv, bool enabled);
int virNetServerStart(virNetServerPtr srv);
+const char *virNetServerGetName(virNetServerPtr srv);
+unsigned int virNetServerGetID(virNetServerPtr srv);
+
#endif /* __VIR_NET_SERVER_H__ */
--
2.4.3
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list