[libvirt] [PATCH 0/6] admin API: Introduce server listing API

I'll send virt-admin list call once the virsh split series is merged. Erik Skultety (6): test: Replace tabs with spaces in input-data-admin-nomdns.json rpc: Introduce new elements 'id' and 'name' to virnetserver structure admin: Drop 'internal.h' include from libvirt-admin.h admin: Move admin_server.{h,c} to admin.{h,c} admin: Introduce adminDaemonConnectListServers API admin: Usage example of the new server listing API .gitignore | 1 + Makefile.am | 2 +- configure.ac | 1 + daemon/Makefile.am | 4 +- daemon/admin.c | 174 +++++++++++++++ daemon/admin.h | 36 +++ daemon/admin_server.c | 116 ++++------ daemon/admin_server.h | 23 +- daemon/libvirtd.c | 6 +- examples/admin/Makefile.am | 25 +++ examples/admin/listservers.c | 73 ++++++ include/libvirt/libvirt-admin.h | 14 +- po/POTFILES.in | 2 +- src/admin/admin_protocol.x | 27 ++- src/datatypes.c | 35 +++ src/datatypes.h | 35 +++ src/libvirt-admin.c | 173 +++++++++++++++ src/libvirt_admin.syms | 4 + src/locking/lock_daemon.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/rpc/virnetdaemon.c | 16 ++ src/rpc/virnetdaemon.h | 2 + src/rpc/virnetserver.c | 41 +++- src/rpc/virnetserver.h | 4 + .../virnetdaemondata/input-data-admin-nomdns.json | 246 +++++++++++---------- .../virnetdaemondata/input-data-anon-clients.json | 1 + .../input-data-initial-nomdns.json | 1 + tests/virnetdaemondata/input-data-initial.json | 1 + tests/virnetdaemontest.c | 2 +- 29 files changed, 846 insertions(+), 223 deletions(-) create mode 100644 daemon/admin.c create mode 100644 daemon/admin.h create mode 100644 examples/admin/Makefile.am create mode 100644 examples/admin/listservers.c -- 2.4.3

JSON data that are used to initialize tests in virnetdaemontest should be in a consistent format, i.e. not using tabs for indentation, those should be replaced by spaces. --- .../virnetdaemondata/input-data-admin-nomdns.json | 244 ++++++++++----------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/tests/virnetdaemondata/input-data-admin-nomdns.json b/tests/virnetdaemondata/input-data-admin-nomdns.json index 59bc471..449bcc9 100644 --- a/tests/virnetdaemondata/input-data-admin-nomdns.json +++ b/tests/virnetdaemondata/input-data-admin-nomdns.json @@ -1,126 +1,126 @@ { "servers": [ - { - "min_workers": 10, - "max_workers": 50, - "priority_workers": 5, - "max_clients": 100, - "keepaliveInterval": 120, - "keepaliveCount": 5, - "keepaliveRequired": true, - "services": [ - { - "auth": 0, - "readonly": true, - "nrequests_client_max": 2, - "socks": [ - { - "fd": 100, - "errfd": -1, - "pid": 0, - "isClient": false - } - ] - }, - { - "auth": 2, - "readonly": false, - "nrequests_client_max": 5, - "socks": [ - { - "fd": 101, - "errfd": -1, - "pid": 0, - "isClient": false - } - ] - } - ], - "clients": [ - { - "auth": 1, - "readonly": true, - "nrequests_max": 15, - "sock": { - "fd": 102, - "errfd": -1, - "pid": -1, - "isClient": true - } - }, - { - "auth": 2, - "readonly": true, - "nrequests_max": 66, - "sock": { - "fd": 103, - "errfd": -1, - "pid": -1, - "isClient": true - } - } - ] - }, - { - "min_workers": 2, - "max_workers": 50, - "priority_workers": 5, - "max_clients": 100, - "keepaliveInterval": 120, - "keepaliveCount": 5, - "keepaliveRequired": true, - "services": [ - { - "auth": 0, - "readonly": true, - "nrequests_client_max": 2, - "socks": [ - { - "fd": 100, - "errfd": -1, - "pid": 0, - "isClient": false - } - ] - }, - { - "auth": 2, - "readonly": false, - "nrequests_client_max": 5, - "socks": [ - { - "fd": 101, - "errfd": -1, - "pid": 0, - "isClient": false - } - ] - } - ], - "clients": [ - { - "auth": 1, - "readonly": true, - "nrequests_max": 15, - "sock": { - "fd": 102, - "errfd": -1, - "pid": -1, - "isClient": true - } - }, - { - "auth": 2, - "readonly": true, - "nrequests_max": 66, - "sock": { - "fd": 103, - "errfd": -1, - "pid": -1, - "isClient": true - } - } - ] - } + { + "min_workers": 10, + "max_workers": 50, + "priority_workers": 5, + "max_clients": 100, + "keepaliveInterval": 120, + "keepaliveCount": 5, + "keepaliveRequired": true, + "services": [ + { + "auth": 0, + "readonly": true, + "nrequests_client_max": 2, + "socks": [ + { + "fd": 100, + "errfd": -1, + "pid": 0, + "isClient": false + } + ] + }, + { + "auth": 2, + "readonly": false, + "nrequests_client_max": 5, + "socks": [ + { + "fd": 101, + "errfd": -1, + "pid": 0, + "isClient": false + } + ] + } + ], + "clients": [ + { + "auth": 1, + "readonly": true, + "nrequests_max": 15, + "sock": { + "fd": 102, + "errfd": -1, + "pid": -1, + "isClient": true + } + }, + { + "auth": 2, + "readonly": true, + "nrequests_max": 66, + "sock": { + "fd": 103, + "errfd": -1, + "pid": -1, + "isClient": true + } + } + ] + }, + { + "min_workers": 2, + "max_workers": 50, + "priority_workers": 5, + "max_clients": 100, + "keepaliveInterval": 120, + "keepaliveCount": 5, + "keepaliveRequired": true, + "services": [ + { + "auth": 0, + "readonly": true, + "nrequests_client_max": 2, + "socks": [ + { + "fd": 100, + "errfd": -1, + "pid": 0, + "isClient": false + } + ] + }, + { + "auth": 2, + "readonly": false, + "nrequests_client_max": 5, + "socks": [ + { + "fd": 101, + "errfd": -1, + "pid": 0, + "isClient": false + } + ] + } + ], + "clients": [ + { + "auth": 1, + "readonly": true, + "nrequests_max": 15, + "sock": { + "fd": 102, + "errfd": -1, + "pid": -1, + "isClient": true + } + }, + { + "auth": 2, + "readonly": true, + "nrequests_max": 66, + "sock": { + "fd": 103, + "errfd": -1, + "pid": -1, + "isClient": true + } + } + ] + } ] } -- 2.4.3

On Tue, Aug 11, 2015 at 09:58:56AM +0200, Erik Skultety wrote:
JSON data that are used to initialize tests in virnetdaemontest should be in a consistent format, i.e. not using tabs for indentation, those should be replaced by spaces. --- .../virnetdaemondata/input-data-admin-nomdns.json | 244 ++++++++++----------- 1 file changed, 122 insertions(+), 122 deletions(-)
I don't know how I screwed that up, but thatnks for fixing. I'm guessing this is not based on top of the "keepalive_required" removal that I probably screwed up the same way, right?

By adding these elements, we'll be able to represent the servers on client side. This is merely because when listing clients or managing clients, it would be convenient to know which server they're connected to. Also reflect this change in virnetdaemontest as well. --- daemon/libvirtd.c | 2 ++ src/locking/lock_daemon.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/rpc/virnetdaemon.c | 1 + src/rpc/virnetserver.c | 17 ++++++++++++++++- src/rpc/virnetserver.h | 1 + tests/virnetdaemondata/input-data-admin-nomdns.json | 2 ++ tests/virnetdaemondata/input-data-anon-clients.json | 1 + tests/virnetdaemondata/input-data-initial-nomdns.json | 1 + tests/virnetdaemondata/input-data-initial.json | 1 + tests/virnetdaemontest.c | 2 +- 11 files changed, 28 insertions(+), 4 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 250094b..88ad753 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -1390,6 +1390,7 @@ int main(int argc, char **argv) { config->keepalive_interval, config->keepalive_count, config->mdns_adv ? config->mdns_name : NULL, + "default", remoteClientInitHook, NULL, remoteClientFreeFunc, @@ -1464,6 +1465,7 @@ int main(int argc, char **argv) { config->admin_keepalive_interval, config->admin_keepalive_count, NULL, + "admin", remoteAdmClientInitHook, NULL, remoteAdmClientFreeFunc, diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index c035024..6e67620 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -151,7 +151,7 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged) if (!(lockd->srv = virNetServerNew(1, 1, 0, config->max_clients, config->max_clients, -1, 0, - NULL, + NULL, "virlockd", virLockDaemonClientNew, virLockDaemonClientPreExecRestart, virLockDaemonClientFree, diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 48a3597..0984be0 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -926,7 +926,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) if (!(srv = virNetServerNew(0, 0, 0, 1, 0, -1, 0, - NULL, + NULL, "LXC", virLXCControllerClientPrivateNew, NULL, virLXCControllerClientPrivateFree, diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c index 910f266..bdfcfb7 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -69,6 +69,7 @@ struct _virNetDaemon { int sigwrite; int sigwatch; + unsigned int nextSrvId; size_t nservers; virNetServerPtr *servers; virJSONValuePtr srvObject; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 80b5588..ae48cbb 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -36,6 +36,7 @@ VIR_LOG_INIT("rpc.netserver"); +static unsigned int nextServerId; typedef struct _virNetServerJob virNetServerJob; typedef virNetServerJob *virNetServerJobPtr; @@ -49,6 +50,8 @@ struct _virNetServerJob { struct _virNetServer { virObjectLockable parent; + char *name; + unsigned int id; virThreadPoolPtr workers; char *mdnsGroupName; @@ -312,6 +315,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, int keepaliveInterval, unsigned int keepaliveCount, const char *mdnsGroupName, + const char *serverName, virNetServerClientPrivNew clientPrivNew, virNetServerClientPrivPreExecRestart clientPrivPreExecRestart, virFreeCallback clientPrivFree, @@ -332,6 +336,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, srv))) goto error; + srv->id = nextServerId++; srv->nclients_max = max_clients; srv->nclients_unauth_max = max_anonymous_clients; srv->keepaliveInterval = keepaliveInterval; @@ -341,6 +346,9 @@ virNetServerPtr virNetServerNew(size_t min_workers, srv->clientPrivFree = clientPrivFree; srv->clientPrivOpaque = clientPrivOpaque; + if (VIR_STRDUP(srv->name, serverName) < 0) + goto error; + if (VIR_STRDUP(srv->mdnsGroupName, mdnsGroupName) < 0) goto error; if (srv->mdnsGroupName) { @@ -378,6 +386,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, unsigned int keepaliveInterval; unsigned int keepaliveCount; const char *mdnsGroupName = NULL; + const char *serverName = NULL; if (virJSONValueObjectGetNumberUint(object, "min_workers", &min_workers) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -427,11 +436,17 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, goto error; } + if (!(serverName = virJSONValueObjectGetString(object, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing server name in JSON document")); + goto error; + } + if (!(srv = virNetServerNew(min_workers, max_workers, priority_workers, max_clients, max_anonymous_clients, keepaliveInterval, keepaliveCount, - mdnsGroupName, + mdnsGroupName, serverName, clientPrivNew, clientPrivPreExecRestart, clientPrivFree, clientPrivOpaque))) goto error; diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index 89d8db9..fb04aa3 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -42,6 +42,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, int keepaliveInterval, unsigned int keepaliveCount, const char *mdnsGroupName, + const char *serverName, virNetServerClientPrivNew clientPrivNew, virNetServerClientPrivPreExecRestart clientPrivPreExecRestart, virFreeCallback clientPrivFree, diff --git a/tests/virnetdaemondata/input-data-admin-nomdns.json b/tests/virnetdaemondata/input-data-admin-nomdns.json index 449bcc9..9f2281c 100644 --- a/tests/virnetdaemondata/input-data-admin-nomdns.json +++ b/tests/virnetdaemondata/input-data-admin-nomdns.json @@ -8,6 +8,7 @@ "keepaliveInterval": 120, "keepaliveCount": 5, "keepaliveRequired": true, + "name": "libvirtTestServer0", "services": [ { "auth": 0, @@ -69,6 +70,7 @@ "keepaliveInterval": 120, "keepaliveCount": 5, "keepaliveRequired": true, + "name": "libvirtTestServer1", "services": [ { "auth": 0, diff --git a/tests/virnetdaemondata/input-data-anon-clients.json b/tests/virnetdaemondata/input-data-anon-clients.json index 8a51ff5..3bc84f7 100644 --- a/tests/virnetdaemondata/input-data-anon-clients.json +++ b/tests/virnetdaemondata/input-data-anon-clients.json @@ -7,6 +7,7 @@ "keepaliveInterval": 120, "keepaliveCount": 5, "keepaliveRequired": true, + "name": "libvirtTestServer", "services": [ { "auth": 0, diff --git a/tests/virnetdaemondata/input-data-initial-nomdns.json b/tests/virnetdaemondata/input-data-initial-nomdns.json index 02bb427..f755a29 100644 --- a/tests/virnetdaemondata/input-data-initial-nomdns.json +++ b/tests/virnetdaemondata/input-data-initial-nomdns.json @@ -6,6 +6,7 @@ "keepaliveInterval": 120, "keepaliveCount": 5, "keepaliveRequired": true, + "name": "libvirtTestServer", "services": [ { "auth": 0, diff --git a/tests/virnetdaemondata/input-data-initial.json b/tests/virnetdaemondata/input-data-initial.json index 7956225..d1c801d 100644 --- a/tests/virnetdaemondata/input-data-initial.json +++ b/tests/virnetdaemondata/input-data-initial.json @@ -7,6 +7,7 @@ "keepaliveCount": 5, "keepaliveRequired": true, "mdnsGroupName": "libvirtTest", + "name": "libvirtTestServer", "services": [ { "auth": 0, diff --git a/tests/virnetdaemontest.c b/tests/virnetdaemontest.c index fb8a6c0..019c8c4 100644 --- a/tests/virnetdaemontest.c +++ b/tests/virnetdaemontest.c @@ -51,7 +51,7 @@ testCreateServer(const char *host, int family) if (!(srv = virNetServerNew(10, 50, 5, 100, 10, 120, 5, - mdns_group, + mdns_group, "test-server", NULL, NULL, NULL, -- 2.4.3

On Tue, Aug 11, 2015 at 09:58:57AM +0200, Erik Skultety wrote:
By adding these elements, we'll be able to represent the servers on client side. This is merely because when listing clients or managing clients, it would be convenient to know which server they're connected to. Also reflect this change in virnetdaemontest as well. --- daemon/libvirtd.c | 2 ++ src/locking/lock_daemon.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/rpc/virnetdaemon.c | 1 + src/rpc/virnetserver.c | 17 ++++++++++++++++- src/rpc/virnetserver.h | 1 + tests/virnetdaemondata/input-data-admin-nomdns.json | 2 ++ tests/virnetdaemondata/input-data-anon-clients.json | 1 + tests/virnetdaemondata/input-data-initial-nomdns.json | 1 + tests/virnetdaemondata/input-data-initial.json | 1 + tests/virnetdaemontest.c | 2 +- 11 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 250094b..88ad753 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -1390,6 +1390,7 @@ int main(int argc, char **argv) { config->keepalive_interval, config->keepalive_count, config->mdns_adv ? config->mdns_name : NULL, + "default",
You're using "default" here, ...
remoteClientInitHook, NULL, remoteClientFreeFunc, diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index c035024..6e67620 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -151,7 +151,7 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged)
if (!(lockd->srv = virNetServerNew(1, 1, 0, config->max_clients, config->max_clients, -1, 0, - NULL, + NULL, "virlockd",
... but "virlockd" for the virtlockd (notice your missing 't'). We should be consistent with that, so either use "default" for all default ones or name them based on the binary.
diff --git a/tests/virnetdaemondata/input-data-initial.json b/tests/virnetdaemondata/input-data-initial.json index 7956225..d1c801d 100644 --- a/tests/virnetdaemondata/input-data-initial.json +++ b/tests/virnetdaemondata/input-data-initial.json @@ -7,6 +7,7 @@ "keepaliveCount": 5, "keepaliveRequired": true, "mdnsGroupName": "libvirtTest", + "name": "libvirtTestServer", "services": [ { "auth": 0,
Input data should not have added any field. Read the README in this directory. The input*.json files are what the real binary will read in real life (not tests), so that's exactly what we need to test for.
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 80b5588..ae48cbb 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -427,11 +436,17 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, goto error; }
+ if (!(serverName = virJSONValueObjectGetString(object, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing server name in JSON document")); + goto error; + } +
And that's why we must *not* fail here. I would rather you add a name of the server to the function being called here. That name will be used in case there is no server name in the input JSON file. It's also easy to test in virnetdaemontest -- you add different default name in the parameter and leave different one in the file. Those files without the name will have the default one in output and the new one will have the same one in output.

This is a public library, it shouldn't include anything that is internal. Including the library in it's current state to an example application fails the preprocessor phase. --- include/libvirt/libvirt-admin.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index b3cfc93..9997cc2 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -26,8 +26,6 @@ #ifndef __VIR_ADMIN_H__ # define __VIR_ADMIN_H__ -# include "internal.h" - # ifdef __cplusplus extern "C" { # endif -- 2.4.3

On Tue, Aug 11, 2015 at 09:58:58AM +0200, Erik Skultety wrote:
This is a public library, it shouldn't include anything that is internal. Including the library in it's current state to an example application fails the preprocessor phase. --- include/libvirt/libvirt-admin.h | 2 -- 1 file changed, 2 deletions(-)
ACK as-is (independent of other patches, feel free to push this ASAP.
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index b3cfc93..9997cc2 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -26,8 +26,6 @@ #ifndef __VIR_ADMIN_H__ # define __VIR_ADMIN_H__
-# include "internal.h" - # ifdef __cplusplus extern "C" { # endif -- 2.4.3
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 11/08/15 10:22, Martin Kletzander wrote:
On Tue, Aug 11, 2015 at 09:58:58AM +0200, Erik Skultety wrote:
This is a public library, it shouldn't include anything that is internal. Including the library in it's current state to an example application fails the preprocessor phase. --- include/libvirt/libvirt-admin.h | 2 -- 1 file changed, 2 deletions(-)
ACK as-is (independent of other patches, feel free to push this ASAP.
pushed now, thanks. Erik

This change is merely because admin_server would contain all the code from dispatchers and helpers to the actual APIs. Admin should have similar structure to the daemon-side remote driver - dispatchers and helpers in a separate module, APIs in a separate module. --- daemon/Makefile.am | 4 +- daemon/admin.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++ daemon/admin.h | 36 ++++++++++++++++ daemon/admin_server.c | 117 -------------------------------------------------- daemon/admin_server.h | 36 ---------------- daemon/libvirtd.c | 4 +- po/POTFILES.in | 2 +- 7 files changed, 158 insertions(+), 158 deletions(-) create mode 100644 daemon/admin.c create mode 100644 daemon/admin.h delete mode 100644 daemon/admin_server.c delete mode 100644 daemon/admin_server.h diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 59bc4d4..5637f5a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -128,7 +128,7 @@ libvirtd_conf_la_LIBADD = $(LIBXML_LIBS) noinst_LTLIBRARIES += libvirtd_admin.la libvirtd_admin_la_SOURCES = \ - admin_server.c admin_server.h + admin.c admin.h libvirtd_admin_la_CFLAGS = \ $(AM_CFLAGS) \ @@ -319,7 +319,7 @@ endif ! WITH_POLKIT remote.c: $(DAEMON_GENERATED) remote.h: $(DAEMON_GENERATED) -admin_server.c: $(DAEMON_GENERATED) +admin.c: $(DAEMON_GENERATED) LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \ libvirtd.libxl.logrotate libvirtd.uml.logrotate \ diff --git a/daemon/admin.c b/daemon/admin.c new file mode 100644 index 0000000..ef404a9 --- /dev/null +++ b/daemon/admin.c @@ -0,0 +1,117 @@ +/* + * admin.c: handlers for RPC method calls + * + * 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@redhat.com> + */ + +#include <config.h> + +#include "internal.h" +#include "libvirtd.h" +#include "libvirt_internal.h" + +#include "admin_protocol.h" +#include "admin.h" +#include "datatypes.h" +#include "viralloc.h" +#include "virerror.h" +#include "virlog.h" +#include "virnetdaemon.h" +#include "virnetserver.h" +#include "virstring.h" +#include "virthreadjob.h" + +#define VIR_FROM_THIS VIR_FROM_ADMIN + +VIR_LOG_INIT("daemon.admin"); + + +void +remoteAdmClientFreeFunc(void *data) +{ + struct daemonAdmClientPrivate *priv = data; + + virMutexDestroy(&priv->lock); + virObjectUnref(priv->dmn); + VIR_FREE(priv); +} + +void * +remoteAdmClientInitHook(virNetServerClientPtr client ATTRIBUTE_UNUSED, + void *opaque) +{ + struct daemonAdmClientPrivate *priv; + + if (VIR_ALLOC(priv) < 0) + return NULL; + + if (virMutexInit(&priv->lock) < 0) { + VIR_FREE(priv); + virReportSystemError(errno, "%s", _("unable to init mutex")); + return NULL; + } + + /* + * We don't necessarily need to ref this object right now as there + * must be one ref being held throughout the life of the daemon, + * but let's just be safe for future. + */ + priv->dmn = virObjectRef(opaque); + + return priv; +} + +/* Functions */ +static int +adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + struct admin_connect_open_args *args) +{ + unsigned int flags; + struct daemonAdmClientPrivate *priv = + virNetServerClientGetPrivateData(client); + int ret = -1; + + VIR_DEBUG("priv=%p dmn=%p", priv, priv->dmn); + virMutexLock(&priv->lock); + + flags = args->flags; + virCheckFlagsGoto(0, cleanup); + + ret = 0; + cleanup: + if (ret < 0) + virNetMessageSaveError(rerr); + virMutexUnlock(&priv->lock); + return ret; +} + +static int +adminDispatchConnectClose(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED) +{ + virNetServerClientDelayedClose(client); + return 0; +} + +#include "admin_dispatch.h" diff --git a/daemon/admin.h b/daemon/admin.h new file mode 100644 index 0000000..6262026 --- /dev/null +++ b/daemon/admin.h @@ -0,0 +1,36 @@ +/* + * admin.h: handlers for RPC method calls + * + * 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@redhat.com> + */ + +#ifndef __LIBVIRTD_ADMIN_H__ +# define __LIBVIRTD_ADMIN_H__ + +# include "rpc/virnetserverprogram.h" +# include "rpc/virnetserverclient.h" + + +extern virNetServerProgramProc adminProcs[]; +extern size_t adminNProcs; + +void remoteAdmClientFreeFunc(void *data); +void *remoteAdmClientInitHook(virNetServerClientPtr client, void *opaque); + +#endif /* __LIBVIRTD_ADMIN_H__ */ diff --git a/daemon/admin_server.c b/daemon/admin_server.c deleted file mode 100644 index 712a44b..0000000 --- a/daemon/admin_server.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * admin_server.c: - * - * 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@redhat.com> - */ - -#include <config.h> - -#include "internal.h" -#include "libvirtd.h" -#include "libvirt_internal.h" - -#include "admin_protocol.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" -#include "virthreadjob.h" - -#define VIR_FROM_THIS VIR_FROM_ADMIN - -VIR_LOG_INIT("daemon.admin"); - - -void -remoteAdmClientFreeFunc(void *data) -{ - struct daemonAdmClientPrivate *priv = data; - - virMutexDestroy(&priv->lock); - virObjectUnref(priv->dmn); - VIR_FREE(priv); -} - -void * -remoteAdmClientInitHook(virNetServerClientPtr client ATTRIBUTE_UNUSED, - void *opaque) -{ - struct daemonAdmClientPrivate *priv; - - if (VIR_ALLOC(priv) < 0) - return NULL; - - if (virMutexInit(&priv->lock) < 0) { - VIR_FREE(priv); - virReportSystemError(errno, "%s", _("unable to init mutex")); - return NULL; - } - - /* - * We don't necessarily need to ref this object right now as there - * must be one ref being held throughout the life of the daemon, - * but let's just be safe for future. - */ - priv->dmn = virObjectRef(opaque); - - return priv; -} - -/* Functions */ -static int -adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client, - virNetMessagePtr msg ATTRIBUTE_UNUSED, - virNetMessageErrorPtr rerr, - struct admin_connect_open_args *args) -{ - unsigned int flags; - struct daemonAdmClientPrivate *priv = - virNetServerClientGetPrivateData(client); - int ret = -1; - - VIR_DEBUG("priv=%p dmn=%p", priv, priv->dmn); - virMutexLock(&priv->lock); - - flags = args->flags; - virCheckFlagsGoto(0, cleanup); - - ret = 0; - cleanup: - if (ret < 0) - virNetMessageSaveError(rerr); - virMutexUnlock(&priv->lock); - return ret; -} - -static int -adminDispatchConnectClose(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client, - virNetMessagePtr msg ATTRIBUTE_UNUSED, - virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED) -{ - virNetServerClientDelayedClose(client); - return 0; -} - -#include "admin_dispatch.h" diff --git a/daemon/admin_server.h b/daemon/admin_server.h deleted file mode 100644 index 26721a6..0000000 --- a/daemon/admin_server.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * admin_server.h - * - * Copyright (C) 2014 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@redhat.com> - */ - -#ifndef __LIBVIRTD_ADMIN_H__ -# define __LIBVIRTD_ADMIN_H__ - -# include "rpc/virnetserverprogram.h" -# include "rpc/virnetserverclient.h" - - -extern virNetServerProgramProc adminProcs[]; -extern size_t adminNProcs; - -void remoteAdmClientFreeFunc(void *data); -void *remoteAdmClientInitHook(virNetServerClientPtr client, void *opaque); - -#endif /* __ADMIN_REMOTE_H__ */ diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 88ad753..109c619 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -44,7 +44,7 @@ #include "libvirtd.h" #include "libvirtd-config.h" -#include "admin_server.h" +#include "admin.h" #include "viruuid.h" #include "remote_driver.h" #include "viralloc.h" @@ -523,7 +523,7 @@ daemonSetupNetworking(virNetServerPtr srv, goto cleanup; /* Temporarily disabled */ - if (sock_path_adm && false) { + if (sock_path_adm) { VIR_DEBUG("Registering unix socket %s", sock_path_adm); if (!(svcAdm = virNetServerServiceNewUNIX(sock_path_adm, unix_sock_adm_mask, diff --git a/po/POTFILES.in b/po/POTFILES.in index c58a7c1..16f0ad4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,4 @@ -daemon/admin_server.c +daemon/admin.c daemon/libvirtd-config.c daemon/libvirtd.c daemon/qemu_dispatch.h -- 2.4.3

On Tue, Aug 11, 2015 at 09:58:59AM +0200, Erik Skultety wrote:
This change is merely because admin_server would contain all the code from dispatchers and helpers to the actual APIs. Admin should have similar structure to the daemon-side remote driver - dispatchers and helpers in a separate module, APIs in a separate module. --- daemon/Makefile.am | 4 +- daemon/admin.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++ daemon/admin.h | 36 ++++++++++++++++ daemon/admin_server.c | 117 -------------------------------------------------- daemon/admin_server.h | 36 ---------------- daemon/libvirtd.c | 4 +- po/POTFILES.in | 2 +- 7 files changed, 158 insertions(+), 158 deletions(-) create mode 100644 daemon/admin.c create mode 100644 daemon/admin.h delete mode 100644 daemon/admin_server.c delete mode 100644 daemon/admin_server.h
Either rename these with 'git mv', format the patch with -M or at least note in the commit message that this is best viewed with -M. Or all of those together :)

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 | 83 +++++++++++++++++++ daemon/admin_server.h | 33 ++++++++ include/libvirt/libvirt-admin.h | 12 +++ src/admin/admin_protocol.x | 27 ++++++- src/datatypes.c | 35 ++++++++ src/datatypes.h | 35 ++++++++ src/libvirt-admin.c | 173 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_admin.syms | 4 + src/rpc/virnetdaemon.c | 15 ++++ src/rpc/virnetdaemon.h | 2 + src/rpc/virnetserver.c | 24 ++++++ src/rpc/virnetserver.h | 3 + 14 files changed, 503 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 5637f5a..d4dd4ac 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -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) \ diff --git a/daemon/admin.c b/daemon/admin.c index ef404a9..d765231 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, + 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..9af94ee --- /dev/null +++ b/daemon/admin_server.c @@ -0,0 +1,83 @@ +/* + * 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@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))) { + virObjectUnlock(srv); + goto cleanup; + } + + srvs[i]->id = id; + 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@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 9997cc2..83e73ca 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -39,6 +39,8 @@ extern "C" { */ typedef struct _virAdmConnect virAdmConnect; +typedef struct _virAdmServer virAdmServer; + /** * virAdmConnectPtr: * @@ -48,11 +50,21 @@ typedef struct _virAdmConnect virAdmConnect; */ typedef virAdmConnect *virAdmConnectPtr; +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 cfc92ff..05b31ea 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -30,17 +30,36 @@ */ const ADMIN_STRING_MAX = 4194304; +/* Upper limit on list of servers */ +const ADMIN_SERVER_LIST_MAX = 16384; + /* A long string, which may NOT be NULL. */ typedef string admin_nonnull_string<ADMIN_STRING_MAX>; /* A long string, which may be NULL. */ typedef admin_nonnull_string *admin_string; +/* A server which may NOT be NULL */ +struct admin_nonnull_server { + admin_nonnull_string name; + unsigned hyper id; +}; + /*----- Protocol. -----*/ 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; @@ -71,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/datatypes.c b/src/datatypes.c index 12bcfc1..98d0661 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -60,8 +60,10 @@ static void virStorageVolDispose(void *obj); static void virStoragePoolDispose(void *obj); virClassPtr virAdmConnectClass; +virClassPtr virAdmServerClass; static void virAdmConnectDispose(void *obj); +static void virAdmServerDispose(void *obj); static int virDataTypesOnceInit(void) @@ -90,6 +92,7 @@ virDataTypesOnceInit(void) DECLARE_CLASS(virStorageVol); DECLARE_CLASS(virStoragePool); + DECLARE_CLASS(virAdmServer); DECLARE_CLASS_LOCKABLE(virAdmConnect); #undef DECLARE_CLASS_COMMON @@ -833,3 +836,35 @@ virAdmConnectDispose(void *obj) if (conn->privateDataFreeFunc) conn->privateDataFreeFunc(conn); } + +virAdmServerPtr +virAdmGetServer(virAdmConnectPtr conn, const char *name) +{ + virAdmServerPtr ret = NULL; + + if (virDataTypesInitialize() < 0) + goto error; + + if (!(ret = virObjectNew(virAdmServerClass))) + goto error; + if (VIR_STRDUP(ret->name, name) < 0) + goto error; + + ret->conn = virObjectRef(conn); + ret->id = -1; + + return ret; + error: + virObjectUnref(ret); + return NULL; +} + +static void +virAdmServerDispose(void *obj) +{ + virAdmServerPtr srv = obj; + VIR_DEBUG("release server %p %d", srv, srv->id); + + VIR_FREE(srv->name); + virObjectUnref(srv->conn); +} diff --git a/src/datatypes.h b/src/datatypes.h index be108fe..4e0603d 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -42,6 +42,7 @@ extern virClassPtr virStorageVolClass; extern virClassPtr virStoragePoolClass; extern virClassPtr virAdmConnectClass; +extern virClassPtr virAdmServerClass; # define virCheckConnectReturn(obj, retval) \ do { \ @@ -317,6 +318,26 @@ extern virClassPtr virAdmConnectClass; } \ } while (0) +# define virCheckAdmServerReturn(obj, retval) \ + do { \ + if (!virObjectIsClass(obj, virAdmServerClass)) { \ + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + virDispatchError(NULL); \ + return retval; \ + } \ + } while (0) +# define virCheckAdmServerGoto(obj, label) \ + do { \ + if (!virObjectIsClass(obj, virAdmServerClass)) { \ + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + goto label; \ + } \ + } while (0); + /** * VIR_DOMAIN_DEBUG: * @dom: domain @@ -402,6 +423,18 @@ struct _virAdmConnect { virFreeCallback privateDataFreeFunc; }; +/** + * _virAdmServer: + * + * Internal structure associated to a daemon server + */ +struct _virAdmServer { + virObject object; + virAdmConnectPtr conn; /* pointer back to the admin connection */ + char *name; /* the server external name */ + unsigned int id; /* the server unique ID */ +}; + /** * _virDomain: @@ -586,4 +619,6 @@ virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain, virAdmConnectPtr virAdmConnectNew(void); +virAdmServerPtr virAdmGetServer(virAdmConnectPtr conn, + const char *name); #endif /* __VIR_DATATYPES_H__ */ diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index b3fd0b3..c8ea877 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -123,6 +123,18 @@ 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); + if (srv) + srv->id = server.id; + return srv; +} + static bool virAdmGlobalError; static virOnceControl virAdmGlobalOnce = VIR_ONCE_CONTROL_INITIALIZER; @@ -385,3 +397,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.syms b/src/libvirt_admin.syms index d9e3c0b..dbb5f76 100644 --- a/src/libvirt_admin.syms +++ b/src/libvirt_admin.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 bdfcfb7..64496c4 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -205,6 +205,21 @@ 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; +} + + virNetServerPtr virNetDaemonAddServerPostExec(virNetDaemonPtr dmn, virNetServerClientPrivNew clientPrivNew, diff --git a/src/rpc/virnetdaemon.h b/src/rpc/virnetdaemon.h index bb32053..908a49c 100644 --- a/src/rpc/virnetdaemon.h +++ b/src/rpc/virnetdaemon.h @@ -80,5 +80,7 @@ bool virNetDaemonHasClients(virNetDaemonPtr dmn); virNetServerPtr virNetDaemonGetServer(virNetDaemonPtr dmn, int subServerID); +size_t virNetDaemonGetServers(virNetDaemonPtr dmn, + virNetServerPtr **servers); #endif /* __VIR_NET_DAEMON_H__ */ diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index ae48cbb..2544864 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -830,6 +830,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 fb04aa3..873cb3e 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -86,4 +86,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

On Tue, Aug 11, 2015 at 09:59:00AM +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 | 83 +++++++++++++++++++ daemon/admin_server.h | 33 ++++++++ include/libvirt/libvirt-admin.h | 12 +++ src/admin/admin_protocol.x | 27 ++++++- src/datatypes.c | 35 ++++++++ src/datatypes.h | 35 ++++++++ src/libvirt-admin.c | 173 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_admin.syms | 4 + src/rpc/virnetdaemon.c | 15 ++++ src/rpc/virnetdaemon.h | 2 + src/rpc/virnetserver.c | 24 ++++++ src/rpc/virnetserver.h | 3 + 14 files changed, 503 insertions(+), 2 deletions(-) create mode 100644 daemon/admin_server.c create mode 100644 daemon/admin_server.h
I would probably split the introduction of the virAdmServer structure into separate patch. You also forgot to update the admin_protocol-structs, I guess.
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 5637f5a..d4dd4ac 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -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) \ diff --git a/daemon/admin.c b/daemon/admin.c index ef404a9..d765231 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)
Indentation's off.
+{ + 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, + 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..9af94ee --- /dev/null +++ b/daemon/admin_server.c @@ -0,0 +1,83 @@ +/* + * 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@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))) { + virObjectUnlock(srv); + goto cleanup; + } + + srvs[i]->id = id; + 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@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 9997cc2..83e73ca 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -39,6 +39,8 @@ extern "C" { */ typedef struct _virAdmConnect virAdmConnect;
+typedef struct _virAdmServer virAdmServer; + /** * virAdmConnectPtr: * @@ -48,11 +50,21 @@ typedef struct _virAdmConnect virAdmConnect; */ typedef virAdmConnect *virAdmConnectPtr;
+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 cfc92ff..05b31ea 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -30,17 +30,36 @@ */ const ADMIN_STRING_MAX = 4194304;
+/* Upper limit on list of servers */ +const ADMIN_SERVER_LIST_MAX = 16384; + /* A long string, which may NOT be NULL. */ typedef string admin_nonnull_string<ADMIN_STRING_MAX>;
/* A long string, which may be NULL. */ typedef admin_nonnull_string *admin_string;
+/* A server which may NOT be NULL */ +struct admin_nonnull_server { + admin_nonnull_string name; + unsigned hyper id; +}; + /*----- Protocol. -----*/ 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; @@ -71,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/datatypes.c b/src/datatypes.c index 12bcfc1..98d0661 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -60,8 +60,10 @@ static void virStorageVolDispose(void *obj); static void virStoragePoolDispose(void *obj);
virClassPtr virAdmConnectClass; +virClassPtr virAdmServerClass;
static void virAdmConnectDispose(void *obj); +static void virAdmServerDispose(void *obj);
static int virDataTypesOnceInit(void) @@ -90,6 +92,7 @@ virDataTypesOnceInit(void) DECLARE_CLASS(virStorageVol); DECLARE_CLASS(virStoragePool);
+ DECLARE_CLASS(virAdmServer); DECLARE_CLASS_LOCKABLE(virAdmConnect);
#undef DECLARE_CLASS_COMMON @@ -833,3 +836,35 @@ virAdmConnectDispose(void *obj) if (conn->privateDataFreeFunc) conn->privateDataFreeFunc(conn); } + +virAdmServerPtr +virAdmGetServer(virAdmConnectPtr conn, const char *name) +{ + virAdmServerPtr ret = NULL; + + if (virDataTypesInitialize() < 0) + goto error; + + if (!(ret = virObjectNew(virAdmServerClass))) + goto error; + if (VIR_STRDUP(ret->name, name) < 0) + goto error; + + ret->conn = virObjectRef(conn); + ret->id = -1; + + return ret; + error: + virObjectUnref(ret); + return NULL; +} + +static void +virAdmServerDispose(void *obj) +{ + virAdmServerPtr srv = obj; + VIR_DEBUG("release server %p %d", srv, srv->id); + + VIR_FREE(srv->name); + virObjectUnref(srv->conn); +} diff --git a/src/datatypes.h b/src/datatypes.h index be108fe..4e0603d 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -42,6 +42,7 @@ extern virClassPtr virStorageVolClass; extern virClassPtr virStoragePoolClass;
extern virClassPtr virAdmConnectClass; +extern virClassPtr virAdmServerClass;
# define virCheckConnectReturn(obj, retval) \ do { \ @@ -317,6 +318,26 @@ extern virClassPtr virAdmConnectClass; } \ } while (0)
+# define virCheckAdmServerReturn(obj, retval) \ + do { \ + if (!virObjectIsClass(obj, virAdmServerClass)) { \ + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + virDispatchError(NULL); \ + return retval; \ + } \ + } while (0) +# define virCheckAdmServerGoto(obj, label) \ + do { \ + if (!virObjectIsClass(obj, virAdmServerClass)) { \ + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + goto label; \ + } \ + } while (0); + /** * VIR_DOMAIN_DEBUG: * @dom: domain @@ -402,6 +423,18 @@ struct _virAdmConnect { virFreeCallback privateDataFreeFunc; };
+/** + * _virAdmServer: + * + * Internal structure associated to a daemon server + */ +struct _virAdmServer { + virObject object; + virAdmConnectPtr conn; /* pointer back to the admin connection */ + char *name; /* the server external name */ + unsigned int id; /* the server unique ID */ +}; +
/** * _virDomain: @@ -586,4 +619,6 @@ virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain,
virAdmConnectPtr virAdmConnectNew(void);
+virAdmServerPtr virAdmGetServer(virAdmConnectPtr conn, + const char *name); #endif /* __VIR_DATATYPES_H__ */ diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index b3fd0b3..c8ea877 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -123,6 +123,18 @@ 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); + if (srv) + srv->id = server.id;
I wonder why you set the name in the virAdmGetServer() function but id outside of that function. Is there any reason for that which I missed?

Not to be actually pushed since majority of this example will be merged into virt-admin once it's ready, i.e. virsh splitting series is merged, but might be good to just see the API's working. --- .gitignore | 1 + Makefile.am | 2 +- configure.ac | 1 + examples/admin/Makefile.am | 25 +++++++++++++++ examples/admin/listservers.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 examples/admin/Makefile.am create mode 100644 examples/admin/listservers.c diff --git a/.gitignore b/.gitignore index 0b40f4a..325f04f 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ /docs/libvirt-refs.xml /docs/search.php /docs/todo.html.in +/examples/admin/listservers /examples/object-events/event-test /examples/dominfo/info1 /examples/domsuspend/suspend diff --git a/Makefile.am b/Makefile.am index 91b943b..c14229e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \ examples/dominfo examples/domsuspend examples/apparmor \ examples/xml/nwfilter examples/openauth examples/systemtap \ tools/wireshark examples/dommigrate \ - examples/lxcconvert examples/domtop + examples/lxcconvert examples/domtop examples/admin ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index 46c80ce..35c8cd9 100644 --- a/configure.ac +++ b/configure.ac @@ -2805,6 +2805,7 @@ AC_CONFIG_FILES([\ examples/systemtap/Makefile \ examples/xml/nwfilter/Makefile \ examples/lxcconvert/Makefile \ + examples/admin/Makefile \ tools/wireshark/Makefile \ tools/wireshark/src/Makefile]) AC_OUTPUT diff --git a/examples/admin/Makefile.am b/examples/admin/Makefile.am new file mode 100644 index 0000000..8373132 --- /dev/null +++ b/examples/admin/Makefile.am @@ -0,0 +1,25 @@ +## Copyright (C) 2005-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/>. + +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include +LDADDS = $(STATIC_BINARIES) $(WARN_CFLAGS) \ + $(top_builddir)/src/libvirt-admin.la $(COVERAGE_LDFLAGS) + +noinst_PROGRAMS=listservers + +listservers_SOURCES=listservers.c +listservers_LDFLAGS= +listservers_LDADD= $(LDADDS) diff --git a/examples/admin/listservers.c b/examples/admin/listservers.c new file mode 100644 index 0000000..6f11d8d --- /dev/null +++ b/examples/admin/listservers.c @@ -0,0 +1,73 @@ +/* + * listservers.c: Demo program to show listing of available servers + * + * 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: Erik Skultety <eskultet@redhat.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <libvirt/libvirt-admin.h> + +static int +listDaemonServers(void) +{ + int ret = -1; + virAdmConnectPtr conn = NULL; + virAdmServerPtr *srvs = NULL; + int nsrvs = 0; + size_t i; + + /* Connect to an admin server on a specific daemon, NULL in this case means + * connect to libvirtd UNIX socket + */ + if (!(conn = virAdmConnectOpen(NULL, 0))) { + fprintf(stderr, "Failed to connect to the admin server\n"); + goto cleanup; + } + + /* Obtain a list of available servers on the daemon */ + if ((nsrvs = virAdmConnectListServers(conn, &srvs, 0)) < 0) { + fprintf(stderr, "Failed to obtain list of available servers\n"); + goto cleanup; + } + + printf(" %-5s %-15s\n", "Id", "Name"); + printf("---------------\n"); + for (i = 0; i < nsrvs; i++) + printf(" %-5d %-15s\n", virAdmGetServerID(srvs[i]), + virAdmGetServerName(srvs[i])); + + ret = nsrvs; + + cleanup: + if (conn) + virAdmConnectClose(conn); + if (srvs) { + for (i = 0; i < nsrvs; i++) + virAdmServerFree(srvs[i]); + free(srvs); + } + + return ret; +} + +int main(void) +{ + return listDaemonServers(); +} -- 2.4.3

On Tue, Aug 11, 2015 at 09:59:01AM +0200, Erik Skultety wrote:
Not to be actually pushed since majority of this example will be merged into virt-admin once it's ready, i.e. virsh splitting series is merged, but might be good to just see the API's working. ---
I would say "please note in the subject that this is not to be pushed", but since even I can screw that up and push it afterwards, it seems to be said by the wrong person :)
.gitignore | 1 + Makefile.am | 2 +- configure.ac | 1 + examples/admin/Makefile.am | 25 +++++++++++++++ examples/admin/listservers.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 examples/admin/Makefile.am create mode 100644 examples/admin/listservers.c
diff --git a/.gitignore b/.gitignore index 0b40f4a..325f04f 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ /docs/libvirt-refs.xml /docs/search.php /docs/todo.html.in +/examples/admin/listservers /examples/object-events/event-test /examples/dominfo/info1 /examples/domsuspend/suspend diff --git a/Makefile.am b/Makefile.am index 91b943b..c14229e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \ examples/dominfo examples/domsuspend examples/apparmor \ examples/xml/nwfilter examples/openauth examples/systemtap \ tools/wireshark examples/dommigrate \ - examples/lxcconvert examples/domtop + examples/lxcconvert examples/domtop examples/admin
ACLOCAL_AMFLAGS = -I m4
diff --git a/configure.ac b/configure.ac index 46c80ce..35c8cd9 100644 --- a/configure.ac +++ b/configure.ac @@ -2805,6 +2805,7 @@ AC_CONFIG_FILES([\ examples/systemtap/Makefile \ examples/xml/nwfilter/Makefile \ examples/lxcconvert/Makefile \ + examples/admin/Makefile \ tools/wireshark/Makefile \ tools/wireshark/src/Makefile]) AC_OUTPUT diff --git a/examples/admin/Makefile.am b/examples/admin/Makefile.am new file mode 100644 index 0000000..8373132 --- /dev/null +++ b/examples/admin/Makefile.am @@ -0,0 +1,25 @@ +## Copyright (C) 2005-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/>. + +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include +LDADDS = $(STATIC_BINARIES) $(WARN_CFLAGS) \ + $(top_builddir)/src/libvirt-admin.la $(COVERAGE_LDFLAGS) + +noinst_PROGRAMS=listservers + +listservers_SOURCES=listservers.c +listservers_LDFLAGS= +listservers_LDADD= $(LDADDS) diff --git a/examples/admin/listservers.c b/examples/admin/listservers.c new file mode 100644 index 0000000..6f11d8d --- /dev/null +++ b/examples/admin/listservers.c @@ -0,0 +1,73 @@ +/* + * listservers.c: Demo program to show listing of available servers + * + * 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: Erik Skultety <eskultet@redhat.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <libvirt/libvirt-admin.h> + +static int +listDaemonServers(void) +{ + int ret = -1; + virAdmConnectPtr conn = NULL; + virAdmServerPtr *srvs = NULL; + int nsrvs = 0; + size_t i; + + /* Connect to an admin server on a specific daemon, NULL in this case means + * connect to libvirtd UNIX socket + */ + if (!(conn = virAdmConnectOpen(NULL, 0))) { + fprintf(stderr, "Failed to connect to the admin server\n");
There will be error printed by the default error handler, no need to write out another error.
+ goto cleanup; + } + + /* Obtain a list of available servers on the daemon */ + if ((nsrvs = virAdmConnectListServers(conn, &srvs, 0)) < 0) { + fprintf(stderr, "Failed to obtain list of available servers\n"); + goto cleanup; + } + + printf(" %-5s %-15s\n", "Id", "Name"); + printf("---------------\n"); + for (i = 0; i < nsrvs; i++) + printf(" %-5d %-15s\n", virAdmGetServerID(srvs[i]), + virAdmGetServerName(srvs[i])); + + ret = nsrvs; + + cleanup: + if (conn) + virAdmConnectClose(conn); + if (srvs) { + for (i = 0; i < nsrvs; i++) + virAdmServerFree(srvs[i]); + free(srvs); + } + + return ret; +} + +int main(void) +{ + return listDaemonServers(); +} -- 2.4.3
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
participants (2)
-
Erik Skultety
-
Martin Kletzander