For this to pe properly separated from other protocols used by the
server, there is second server added which allows access to the whole
virNetDaemon to its clients.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
cfg.mk | 3 ++
daemon/Makefile.am | 32 +++++++++++++-
daemon/admin_server.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++
daemon/admin_server.h | 36 ++++++++++++++++
daemon/libvirtd.c | 104 +++++++++++++++++++++++++++++++++++++++-----
daemon/libvirtd.h | 14 +++++-
po/POTFILES.in | 1 +
7 files changed, 294 insertions(+), 13 deletions(-)
create mode 100644 daemon/admin_server.c
create mode 100644 daemon/admin_server.h
diff --git a/cfg.mk b/cfg.mk
index f1b50242c6df..0d1a03ce807b 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1072,6 +1072,7 @@ sc_po_check: \
$(srcdir)/daemon/remote_dispatch.h \
$(srcdir)/daemon/qemu_dispatch.h \
$(srcdir)/src/remote/remote_client_bodies.h \
+ $(srcdir)/daemon/admin_dispatch.h \
$(srcdir)/src/admin/admin_client.h
$(srcdir)/daemon/remote_dispatch.h: $(srcdir)/src/remote/remote_protocol.x
$(MAKE) -C daemon remote_dispatch.h
@@ -1079,6 +1080,8 @@ $(srcdir)/daemon/qemu_dispatch.h:
$(srcdir)/src/remote/qemu_protocol.x
$(MAKE) -C daemon qemu_dispatch.h
$(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protocol.x
$(MAKE) -C src remote/remote_client_bodies.h
+$(srcdir)/daemon/admin_dispatch.h: $(srcdir)/src/admin/admin_protocol.x
+ $(MAKE) -C daemon admin_dispatch.h
$(srcdir)/src/admin/admin_client.h: $(srcdir)/src/admin/admin_protocol.x
$(MAKE) -C src admin/admin_client.h
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 42dec5d79c65..3d45f2a804d5 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
-## Copyright (C) 2005-2014 Red Hat, Inc.
+## 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
@@ -25,6 +25,7 @@ INCLUDES = \
-I$(top_srcdir)/src/conf \
-I$(top_srcdir)/src/rpc \
-I$(top_srcdir)/src/remote \
+ -I$(top_srcdir)/src/admin \
-I$(top_srcdir)/src/access \
$(GETTEXT_CPPFLAGS)
@@ -34,6 +35,7 @@ DAEMON_GENERATED = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
+ admin_dispatch.h \
$(NULL)
DAEMON_SOURCES = \
@@ -49,6 +51,7 @@ EXTRA_DIST = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
+ admin_dispatch.h \
libvirtd.conf \
libvirtd.init.in \
libvirtd.upstart \
@@ -78,6 +81,7 @@ BUILT_SOURCES =
REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x
LXC_PROTOCOL = $(top_srcdir)/src/remote/lxc_protocol.x
QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x
+ADMIN_PROTOCOL = $(top_srcdir)/src/admin/admin_protocol.x
remote_dispatch.h: $(top_srcdir)/src/rpc/gendispatch.pl \
$(REMOTE_PROTOCOL)
@@ -97,6 +101,12 @@ qemu_dispatch.h: $(top_srcdir)/src/rpc/gendispatch.pl \
--mode=server qemu QEMU $(QEMU_PROTOCOL) \
$(srcdir)/qemu_dispatch.h
+admin_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
+ $(ADMIN_PROTOCOL)
+ $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl \
+ --mode=server admin ADMIN $(ADMIN_PROTOCOL) \
+ > $(srcdir)/admin_dispatch.h
+
if WITH_LIBVIRTD
# Build a convenience library, for reuse in tests/libvirtdconftest
@@ -116,6 +126,25 @@ libvirtd_conf_la_LDFLAGS = \
$(NULL)
libvirtd_conf_la_LIBADD = $(LIBXML_LIBS)
+noinst_LTLIBRARIES += libvirtd_admin.la
+libvirtd_admin_la_SOURCES = \
+ admin_server.c \
+ ../src/admin/admin_protocol.c
+
+libvirtd_admin_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(XDR_CFLAGS) \
+ $(PIE_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+
+libvirtd_admin_la_LDFLAGS = \
+ $(PIE_LDFLAGS) \
+ $(RELRO_LDFLAGS) \
+ $(COVERAGE_LDFLAGS) \
+ $(NO_INDIRECT_LDFLAGS)
+
man8_MANS = libvirtd.8
sbin_PROGRAMS = libvirtd
@@ -168,6 +197,7 @@ endif WITH_DTRACE_PROBES
libvirtd_LDADD += \
libvirtd_conf.la \
+ libvirtd_admin.la \
../src/libvirt-lxc.la \
../src/libvirt-qemu.la \
../src/libvirt_driver_remote.la \
diff --git a/daemon/admin_server.c b/daemon/admin_server.c
new file mode 100644
index 000000000000..712a44beca10
--- /dev/null
+++ b/daemon/admin_server.c
@@ -0,0 +1,117 @@
+/*
+ * 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(a)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
new file mode 100644
index 000000000000..26721a6d582b
--- /dev/null
+++ b/daemon/admin_server.h
@@ -0,0 +1,36 @@
+/*
+ * 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(a)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 94103e2d0d8c..368e10ca3549 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -44,6 +44,7 @@
#include "libvirtd.h"
#include "libvirtd-config.h"
+#include "admin_server.h"
#include "viruuid.h"
#include "remote_driver.h"
#include "viralloc.h"
@@ -112,6 +113,7 @@ VIR_LOG_INIT("daemon.libvirtd");
virNetSASLContextPtr saslCtxt = NULL;
#endif
virNetServerProgramPtr remoteProgram = NULL;
+virNetServerProgramPtr adminProgram = NULL;
virNetServerProgramPtr qemuProgram = NULL;
virNetServerProgramPtr lxcProgram = NULL;
@@ -253,18 +255,24 @@ static int
daemonUnixSocketPaths(struct daemonConfig *config,
bool privileged,
char **sockfile,
- char **rosockfile)
+ char **rosockfile,
+ char **admsockfile)
{
if (config->unix_sock_dir) {
if (virAsprintf(sockfile, "%s/libvirt-sock", config->unix_sock_dir)
< 0)
goto error;
- if (privileged &&
- virAsprintf(rosockfile, "%s/libvirt-sock-ro",
config->unix_sock_dir) < 0)
- goto error;
+
+ if (privileged) {
+ if (virAsprintf(rosockfile, "%s/libvirt-sock-ro",
config->unix_sock_dir) < 0)
+ goto error;
+ if (virAsprintf(admsockfile, "%s/libvirt-admin-sock",
config->unix_sock_dir) < 0)
+ goto error;
+ }
} else {
if (privileged) {
if (VIR_STRDUP(*sockfile, LOCALSTATEDIR
"/run/libvirt/libvirt-sock") < 0 ||
- VIR_STRDUP(*rosockfile, LOCALSTATEDIR
"/run/libvirt/libvirt-sock-ro") < 0)
+ VIR_STRDUP(*rosockfile, LOCALSTATEDIR
"/run/libvirt/libvirt-sock-ro") < 0 ||
+ VIR_STRDUP(*admsockfile, LOCALSTATEDIR
"/run/libvirt/libvirt-admin-sock") < 0)
goto error;
} else {
char *rundir = NULL;
@@ -280,7 +288,8 @@ daemonUnixSocketPaths(struct daemonConfig *config,
}
umask(old_umask);
- if (virAsprintf(sockfile, "%s/libvirt-sock", rundir) < 0) {
+ if (virAsprintf(sockfile, "%s/libvirt-sock", rundir) < 0 ||
+ virAsprintf(admsockfile, "%s/libvirt-admin-sock", rundir) <
0) {
VIR_FREE(rundir);
goto error;
}
@@ -427,13 +436,16 @@ static void daemonInitialize(void)
static int ATTRIBUTE_NONNULL(3)
daemonSetupNetworking(virNetServerPtr srv,
+ virNetServerPtr srvAdm,
struct daemonConfig *config,
const char *sock_path,
const char *sock_path_ro,
+ const char *sock_path_adm,
bool ipsock,
bool privileged)
{
virNetServerServicePtr svc = NULL;
+ virNetServerServicePtr svcAdm = NULL;
virNetServerServicePtr svcRO = NULL;
virNetServerServicePtr svcTCP = NULL;
#if WITH_GNUTLS
@@ -442,6 +454,7 @@ daemonSetupNetworking(virNetServerPtr srv,
gid_t unix_sock_gid = 0;
int unix_sock_ro_mask = 0;
int unix_sock_rw_mask = 0;
+ int unix_sock_adm_mask = 0;
unsigned int cur_fd = STDERR_FILENO + 1;
unsigned int nfds = virGetListenFDs();
@@ -461,6 +474,11 @@ daemonSetupNetworking(virNetServerPtr srv,
goto error;
}
+ if (virStrToLong_i(config->unix_sock_admin_perms, NULL, 8,
&unix_sock_adm_mask) != 0) {
+ VIR_ERROR(_("Failed to parse mode '%s'"),
config->unix_sock_admin_perms);
+ goto error;
+ }
+
if (virStrToLong_i(config->unix_sock_rw_perms, NULL, 8, &unix_sock_rw_mask) !=
0) {
VIR_ERROR(_("Failed to parse mode '%s'"),
config->unix_sock_rw_perms);
goto error;
@@ -503,6 +521,24 @@ daemonSetupNetworking(virNetServerPtr srv,
virNetServerAddService(srv, svcRO, NULL) < 0)
goto error;
+ if (sock_path_adm) {
+ VIR_DEBUG("Registering unix socket %s", sock_path_adm);
+ if (!(svcAdm = virNetServerServiceNewUNIX(sock_path_adm,
+ unix_sock_adm_mask,
+ unix_sock_gid,
+ REMOTE_AUTH_NONE,
+#if WITH_GNUTLS
+ NULL,
+#endif
+ true,
+ config->admin_max_queued_clients,
+
config->admin_max_client_requests)))
+ goto error;
+ }
+
+ if (virNetServerAddService(srvAdm, svcAdm, NULL) < 0)
+ goto error;
+
if (ipsock) {
if (config->listen_tcp) {
VIR_DEBUG("Registering TCP socket %s:%s",
@@ -602,6 +638,7 @@ daemonSetupNetworking(virNetServerPtr srv,
virObjectUnref(svcTCP);
virObjectUnref(svc);
virObjectUnref(svcRO);
+ virObjectUnref(svcAdm);
return -1;
}
@@ -1102,6 +1139,7 @@ daemonUsage(const char *argv0, bool privileged)
int main(int argc, char **argv) {
virNetDaemonPtr dmn = NULL;
virNetServerPtr srv = NULL;
+ virNetServerPtr srvAdm = NULL;
char *remote_config_file = NULL;
int statuswrite = -1;
int ret = 1;
@@ -1109,6 +1147,7 @@ int main(int argc, char **argv) {
char *pid_file = NULL;
char *sock_file = NULL;
char *sock_file_ro = NULL;
+ char *sock_file_adm = NULL;
int timeout = -1; /* -t: Shutdown timeout */
int verbose = 0;
int godaemon = 0;
@@ -1276,12 +1315,15 @@ int main(int argc, char **argv) {
if (daemonUnixSocketPaths(config,
privileged,
&sock_file,
- &sock_file_ro) < 0) {
+ &sock_file_ro,
+ &sock_file_adm) < 0) {
VIR_ERROR(_("Can't determine socket paths"));
exit(EXIT_FAILURE);
}
- VIR_DEBUG("Decided on socket paths '%s' and '%s'",
- sock_file, NULLSTR(sock_file_ro));
+ VIR_DEBUG("Decided on socket paths '%s', '%s' and
'%s'",
+ sock_file,
+ NULLSTR(sock_file_ro),
+ NULLSTR(sock_file_adm));
if (godaemon) {
char ebuf[1024];
@@ -1413,6 +1455,40 @@ int main(int argc, char **argv) {
goto cleanup;
}
+ if (!(srvAdm = virNetServerNew(config->admin_min_workers,
+ config->admin_max_workers,
+ 0,
+ config->admin_max_clients,
+ 0,
+ config->admin_keepalive_interval,
+ config->admin_keepalive_count,
+ !!config->admin_keepalive_required,
+ NULL,
+ remoteAdmClientInitHook,
+ NULL,
+ remoteAdmClientFreeFunc,
+ dmn))) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+
+ if (virNetDaemonAddServer(dmn, srvAdm) < 0) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+
+ if (!(adminProgram = virNetServerProgramNew(ADMIN_PROGRAM,
+ ADMIN_PROTOCOL_VERSION,
+ adminProcs,
+ adminNProcs))) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+ if (virNetServerAddProgram(srvAdm, adminProgram) < 0) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
virNetDaemonAutoShutdown(dmn, timeout);
@@ -1453,8 +1529,11 @@ int main(int argc, char **argv) {
virHookCall(VIR_HOOK_DRIVER_DAEMON, "-", VIR_HOOK_DAEMON_OP_START,
0, "start", NULL, NULL);
- if (daemonSetupNetworking(srv, config,
- sock_file, sock_file_ro,
+ if (daemonSetupNetworking(srv, srvAdm,
+ config,
+ sock_file,
+ sock_file_ro,
+ sock_file_adm,
ipsock, privileged) < 0) {
ret = VIR_DAEMON_ERR_NETWORK;
goto cleanup;
@@ -1507,9 +1586,11 @@ int main(int argc, char **argv) {
virObjectUnref(remoteProgram);
virObjectUnref(lxcProgram);
virObjectUnref(qemuProgram);
+ virObjectUnref(adminProgram);
virNetDaemonClose(dmn);
virObjectUnref(dmn);
virObjectUnref(srv);
+ virObjectUnref(srvAdm);
virNetlinkShutdown();
if (statuswrite != -1) {
if (ret != 0) {
@@ -1526,6 +1607,7 @@ int main(int argc, char **argv) {
VIR_FREE(sock_file);
VIR_FREE(sock_file_ro);
+ VIR_FREE(sock_file_adm);
VIR_FREE(pid_file);
VIR_FREE(remote_config_file);
VIR_FREE(run_dir);
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index 02d4101742d8..8c1a904893ab 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -1,7 +1,7 @@
/*
* libvirtd.h: daemon data structure definitions
*
- * Copyright (C) 2006-2014 Red Hat, Inc.
+ * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -30,9 +30,11 @@
# include <rpc/types.h>
# include <rpc/xdr.h>
# include "remote_protocol.h"
+# include "admin_protocol.h"
# include "lxc_protocol.h"
# include "qemu_protocol.h"
# include "virthread.h"
+
# if WITH_SASL
# include "virnetsaslcontext.h"
# endif
@@ -42,6 +44,8 @@ typedef struct daemonClientStream daemonClientStream;
typedef daemonClientStream *daemonClientStreamPtr;
typedef struct daemonClientPrivate daemonClientPrivate;
typedef daemonClientPrivate *daemonClientPrivatePtr;
+typedef struct daemonAdmClientPrivate daemonAdmClientPrivate;
+typedef daemonAdmClientPrivate *daemonAdmClientPrivatePtr;
typedef struct daemonClientEventCallback daemonClientEventCallback;
typedef daemonClientEventCallback *daemonClientEventCallbackPtr;
@@ -71,6 +75,14 @@ struct daemonClientPrivate {
bool keepalive_supported;
};
+/* Separate private data for admin connection */
+struct daemonAdmClientPrivate {
+ /* Just a placeholder, not that there is anything to be locked */
+ virMutex lock;
+
+ virNetDaemonPtr dmn;
+};
+
# if WITH_SASL
extern virNetSASLContextPtr saslCtxt;
# endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4afa2f920824..189e2cc2f4d9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+daemon/admin_server.c
daemon/libvirtd-config.c
daemon/libvirtd.c
daemon/qemu_dispatch.h
--
2.4.3