$(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
$(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
## 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
-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)
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
+ admin_dispatch.h \
$(NULL)
DAEMON_SOURCES = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
+ admin_dispatch.h \
libvirtd.conf \
libvirtd.init.in \
libvirtd.upstart \
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)
--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
$(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
libvirtd_LDADD += \
libvirtd_conf.la \
+ libvirtd_admin.la \
../src/libvirt-lxc.la \
../src/libvirt-qemu.la \
../src/libvirt_driver_remote.la \
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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__ */
#include "libvirtd.h"
#include "libvirtd-config.h"
+#include "admin_server.h"
#include "viruuid.h"
#include "remote_driver.h"
#include "viralloc.h"
virNetSASLContextPtr saslCtxt = NULL;
#endif
virNetServerProgramPtr remoteProgram = NULL;
+virNetServerProgramPtr adminProgram = NULL;
virNetServerProgramPtr qemuProgram = NULL;
virNetServerProgramPtr lxcProgram = NULL;
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;
}
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;
}
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
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();
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;
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",
virObjectUnref(svcTCP);
virObjectUnref(svc);
virObjectUnref(svcRO);
+ virObjectUnref(svcAdm);
return -1;
}
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;
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;
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];
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);
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;
virObjectUnref(remoteProgram);
virObjectUnref(lxcProgram);
virObjectUnref(qemuProgram);
+ virObjectUnref(adminProgram);
virNetDaemonClose(dmn);
virObjectUnref(dmn);
virObjectUnref(srv);
+ virObjectUnref(srvAdm);
virNetlinkShutdown();
if (statuswrite != -1) {
if (ret != 0) {
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);
/*
* 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
# 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
typedef daemonClientStream *daemonClientStreamPtr;
typedef struct daemonClientPrivate daemonClientPrivate;
typedef daemonClientPrivate *daemonClientPrivatePtr;
+typedef struct daemonAdmClientPrivate daemonAdmClientPrivate;
+typedef daemonAdmClientPrivate *daemonAdmClientPrivatePtr;
typedef struct daemonClientEventCallback daemonClientEventCallback;
typedef daemonClientEventCallback *daemonClientEventCallbackPtr;
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
+daemon/admin_server.c
daemon/libvirtd-config.c
daemon/libvirtd.c
daemon/qemu_dispatch.h