[libvirt] [PATCH v2 8/9] admin: Introduce adminDaemonConnectListServers API

Martin Kletzander mkletzan at redhat.com
Thu Sep 3 10:23:08 UTC 2015


On Fri, Aug 21, 2015 at 08:04:09PM +0200, Erik Skultety wrote:
>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 at 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 at 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 at redhat.com
>https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150903/24777a11/attachment-0001.sig>


More information about the libvir-list mailing list