Add a virtlogd-admin-sock can serves the admin protocol for the virtlogd
daemon and define a virtlogd:///{system,session} URI scheme for
connecting to it.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/Makefile.am | 1 +
src/libvirt-admin.c | 20 +++--
src/logging/log_daemon.c | 149 +++++++++++++++++++++++++++--------
src/logging/log_daemon_config.c | 3 +
src/logging/log_daemon_config.h | 1 +
src/logging/test_virtlogd.aug.in | 4 +
src/logging/virtlogd-admin.socket.in | 10 +++
src/logging/virtlogd.aug | 1 +
src/logging/virtlogd.service.in | 1 +
9 files changed, 149 insertions(+), 41 deletions(-)
create mode 100644 src/logging/virtlogd-admin.socket.in
diff --git a/src/Makefile.am b/src/Makefile.am
index fd8756f10c..828306fd35 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2672,6 +2672,7 @@ virtlogd_LDFLAGS = \
$(PIE_LDFLAGS) \
$(NULL)
virtlogd_LDADD = \
+ libvirt_driver_admin.la \
libvirt-net-rpc-server.la \
libvirt-net-rpc.la \
libvirt_util.la \
diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c
index 48e6d7fc8a..9d1bff536b 100644
--- a/src/libvirt-admin.c
+++ b/src/libvirt-admin.c
@@ -38,8 +38,9 @@
#define VIR_FROM_THIS VIR_FROM_ADMIN
-#define LIBVIRTD_ADMIN_SOCK_NAME "/libvirt-admin-sock"
-#define LIBVIRTD_ADMIN_UNIX_SOCKET LOCALSTATEDIR "/run/libvirt"
LIBVIRTD_ADMIN_SOCK_NAME
+#define LIBVIRTD_ADMIN_SOCK_NAME "libvirt-admin-sock"
+#define VIRTLOGD_ADMIN_SOCK_NAME "virtlogd-admin-sock"
+
VIR_LOG_INIT("libvirt-admin");
@@ -128,18 +129,25 @@ getSocketPath(virURIPtr uri)
}
if (!sock_path) {
- if (STRNEQ_NULLABLE(uri->scheme, "libvirtd")) {
+ const char *sockbase = NULL;
+ if (STREQ_NULLABLE(uri->scheme, "libvirtd")) {
+ sockbase = LIBVIRTD_ADMIN_SOCK_NAME;
+ } else if (STREQ_NULLABLE(uri->scheme, "virtlogd")) {
+ sockbase = VIRTLOGD_ADMIN_SOCK_NAME;
+ } else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported URI scheme '%s'"),
NULLSTR(uri->scheme));
goto error;
}
+
if (STREQ_NULLABLE(uri->path, "/system")) {
- if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0)
+ if (virAsprintf(&sock_path, LOCALSTATEDIR "/run/libvirt/%s",
+ sockbase) < 0)
goto error;
} else if (STREQ_NULLABLE(uri->path, "/session")) {
- if (!rundir || virAsprintf(&sock_path, "%s%s", rundir,
- LIBVIRTD_ADMIN_SOCK_NAME) < 0)
+ if (!rundir || virAsprintf(&sock_path, "%s/%s", rundir,
+ sockbase) < 0)
goto error;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
diff --git a/src/logging/log_daemon.c b/src/logging/log_daemon.c
index 33133af2af..d54d26ab9d 100644
--- a/src/logging/log_daemon.c
+++ b/src/logging/log_daemon.c
@@ -32,6 +32,7 @@
#include "log_daemon.h"
#include "log_daemon_config.h"
+#include "admin/admin_server_dispatch.h"
#include "virutil.h"
#include "virfile.h"
#include "virpidfile.h"
@@ -137,7 +138,7 @@ static virLogDaemonPtr
virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged)
{
virLogDaemonPtr logd;
- virNetServerPtr srv;
+ virNetServerPtr srv = NULL;
if (VIR_ALLOC(logd) < 0)
return NULL;
@@ -149,6 +150,9 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged)
return NULL;
}
+ if (!(logd->dmn = virNetDaemonNew()))
+ goto error;
+
if (!(srv = virNetServerNew("virtlogd", 1,
1, 1, 0, config->max_clients,
config->max_clients, -1, 0,
@@ -159,8 +163,22 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged)
(void*)(intptr_t)(privileged ? 0x1 : 0x0))))
goto error;
- if (!(logd->dmn = virNetDaemonNew()) ||
- virNetDaemonAddServer(logd->dmn, srv) < 0)
+ if (virNetDaemonAddServer(logd->dmn, srv) < 0)
+ goto error;
+ virObjectUnref(srv);
+ srv = NULL;
+
+ if (!(srv = virNetServerNew("admin", 1,
+ 1, 1, 0, config->admin_max_clients,
+ config->admin_max_clients, -1, 0,
+ NULL,
+ remoteAdmClientNew,
+ remoteAdmClientPreExecRestart,
+ remoteAdmClientFree,
+ logd->dmn)))
+ goto error;
+
+ if (virNetDaemonAddServer(logd->dmn, srv) < 0)
goto error;
virObjectUnref(srv);
srv = NULL;
@@ -189,7 +207,7 @@ virLogDaemonGetHandler(virLogDaemonPtr dmn)
static virNetServerPtr
-virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
+virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn,
const char *name,
virJSONValuePtr object,
void *opaque)
@@ -202,6 +220,14 @@ virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn
ATTRIBUTE_UNUSED,
virLogDaemonClientPreExecRestart,
virLogDaemonClientFree,
opaque);
+ } else if (STREQ(name, "admin")) {
+ return virNetServerNewPostExecRestart(object,
+ name,
+ remoteAdmClientNew,
+ remoteAdmClientNewPostExecRestart,
+ remoteAdmClientPreExecRestart,
+ remoteAdmClientFree,
+ dmn);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected server name '%s' during
restart"),
@@ -354,10 +380,12 @@ virLogDaemonForkIntoBackground(const char *argv0)
static int
virLogDaemonUnixSocketPaths(bool privileged,
- char **sockfile)
+ char **sockfile,
+ char **adminSockfile)
{
if (privileged) {
- if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock")
< 0)
+ if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock")
< 0 ||
+ VIR_STRDUP(*adminSockfile, LOCALSTATEDIR
"/run/libvirt/virtlogd-admin-sock") < 0)
goto error;
} else {
char *rundir = NULL;
@@ -374,7 +402,8 @@ virLogDaemonUnixSocketPaths(bool privileged,
}
umask(old_umask);
- if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0) {
+ if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0 ||
+ virAsprintf(adminSockfile, "%s/virtlogd-admin-sock", rundir) <
0) {
VIR_FREE(rundir);
goto error;
}
@@ -485,29 +514,50 @@ virLogDaemonSetupSignals(virNetDaemonPtr dmn)
static int
-virLogDaemonSetupNetworkingSystemD(virNetServerPtr srv)
+virLogDaemonSetupNetworkingSystemD(virNetServerPtr logSrv, virNetServerPtr adminSrv)
{
- virNetServerServicePtr svc;
unsigned int nfds;
+ size_t i;
if ((nfds = virGetListenFDs()) == 0)
return 0;
- if (nfds > 1)
+ if (nfds > 2)
VIR_DEBUG("Too many (%d) file descriptors from systemd", nfds);
- nfds = 1;
- /* Systemd passes FDs, starting immediately after stderr,
- * so the first FD we'll get is '3'. */
- if (!(svc = virNetServerServiceNewFD(3, 0,
+ for (i = 0; i < nfds && i < 2; i++) {
+ virNetServerServicePtr svc;
+ char *path = virGetUNIXSocketPath(3 + i);
+ virNetServerPtr srv;
+
+ if (!path)
+ return -1;
+
+ if (strstr(path, "virtlogd-admin-sock")) {
+ srv = adminSrv;
+ } else if (strstr(path, "virtlogd-sock")) {
+ srv = logSrv;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown UNIX socket %s passed in"),
+ path);
+ VIR_FREE(path);
+ return -1;
+ }
+ VIR_FREE(path);
+
+ /* Systemd passes FDs, starting immediately after stderr,
+ * so the first FD we'll get is '3'. */
+ if (!(svc = virNetServerServiceNewFD(3 + i, 0,
#if WITH_GNUTLS
- NULL,
+ NULL,
#endif
- false, 0, 1)))
- return -1;
+ false, 0, 1)))
+ return -1;
- if (virNetServerAddService(srv, svc, NULL) < 0) {
- virObjectUnref(svc);
- return -1;
+ if (virNetServerAddService(srv, svc, NULL) < 0) {
+ virObjectUnref(svc);
+ return -1;
+ }
}
return 1;
}
@@ -878,8 +928,10 @@ virLogDaemonUsage(const char *argv0, bool privileged)
}
int main(int argc, char **argv) {
- virNetServerPtr srv = NULL;
+ virNetServerPtr logSrv = NULL;
+ virNetServerPtr adminSrv = NULL;
virNetServerProgramPtr logProgram = NULL;
+ virNetServerProgramPtr adminProgram = NULL;
char *remote_config_file = NULL;
int statuswrite = -1;
int ret = 1;
@@ -889,6 +941,7 @@ int main(int argc, char **argv) {
char *pid_file = NULL;
int pid_file_fd = -1;
char *sock_file = NULL;
+ char *admin_sock_file = NULL;
int timeout = -1; /* -t: Shutdown timeout */
char *state_file = NULL;
bool implicit_conf = false;
@@ -1016,12 +1069,13 @@ int main(int argc, char **argv) {
VIR_DEBUG("Decided on pid file path '%s'", NULLSTR(pid_file));
if (virLogDaemonUnixSocketPaths(privileged,
- &sock_file) < 0) {
+ &sock_file,
+ &admin_sock_file) < 0) {
VIR_ERROR(_("Can't determine socket paths"));
exit(EXIT_FAILURE);
}
- VIR_DEBUG("Decided on socket paths '%s'",
- sock_file);
+ VIR_DEBUG("Decided on socket paths '%s' and '%s'",
+ sock_file, admin_sock_file);
if (virLogDaemonExecRestartStatePath(privileged,
&state_file) < 0) {
@@ -1098,22 +1152,30 @@ int main(int argc, char **argv) {
goto cleanup;
}
- srv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd");
- if ((rv = virLogDaemonSetupNetworkingSystemD(srv)) < 0) {
+ logSrv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd");
+ adminSrv = virNetDaemonGetServer(logDaemon->dmn, "admin");
+ if ((rv = virLogDaemonSetupNetworkingSystemD(logSrv, adminSrv)) < 0) {
ret = VIR_LOG_DAEMON_ERR_NETWORK;
goto cleanup;
}
/* Only do this, if systemd did not pass a FD */
- if (rv == 0 &&
- virLogDaemonSetupNetworkingNative(srv, sock_file) < 0) {
- ret = VIR_LOG_DAEMON_ERR_NETWORK;
- goto cleanup;
+ if (rv == 0) {
+ if (virLogDaemonSetupNetworkingNative(logSrv, sock_file) < 0 ||
+ virLogDaemonSetupNetworkingNative(adminSrv, admin_sock_file) < 0) {
+ ret = VIR_LOG_DAEMON_ERR_NETWORK;
+ goto cleanup;
+ }
}
- virObjectUnref(srv);
+ virObjectUnref(logSrv);
+ virObjectUnref(adminSrv);
}
- srv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd");
+ logSrv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd");
+ /* If exec-restarting from old virtlogd, we won't have an
+ * admin server present */
+ if (virNetDaemonHasServer(logDaemon->dmn, "admin"))
+ adminSrv = virNetDaemonGetServer(logDaemon->dmn, "admin");
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
@@ -1133,11 +1195,25 @@ int main(int argc, char **argv) {
ret = VIR_LOG_DAEMON_ERR_INIT;
goto cleanup;
}
- if (virNetServerAddProgram(srv, logProgram) < 0) {
+ if (virNetServerAddProgram(logSrv, logProgram) < 0) {
ret = VIR_LOG_DAEMON_ERR_INIT;
goto cleanup;
}
+ if (adminSrv != NULL) {
+ if (!(adminProgram = virNetServerProgramNew(ADMIN_PROGRAM,
+ ADMIN_PROTOCOL_VERSION,
+ adminProcs,
+ adminNProcs))) {
+ ret = VIR_LOG_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+ if (virNetServerAddProgram(adminSrv, adminProgram) < 0) {
+ ret = VIR_LOG_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+ }
+
/* Disable error func, now logging is setup */
virSetErrorFunc(NULL, virLogDaemonErrorHandler);
@@ -1155,7 +1231,7 @@ int main(int argc, char **argv) {
/* Start accepting new clients from network */
- virNetServerUpdateServices(srv, true);
+ virNetDaemonUpdateServices(logDaemon->dmn, true);
virNetDaemonRun(logDaemon->dmn);
if (execRestart &&
@@ -1168,7 +1244,9 @@ int main(int argc, char **argv) {
cleanup:
virObjectUnref(logProgram);
- virObjectUnref(srv);
+ virObjectUnref(adminProgram);
+ virObjectUnref(logSrv);
+ virObjectUnref(adminSrv);
virLogDaemonFree(logDaemon);
if (statuswrite != -1) {
if (ret != 0) {
@@ -1184,6 +1262,7 @@ int main(int argc, char **argv) {
virPidFileReleasePath(pid_file, pid_file_fd);
VIR_FREE(pid_file);
VIR_FREE(sock_file);
+ VIR_FREE(admin_sock_file);
VIR_FREE(state_file);
VIR_FREE(run_dir);
VIR_FREE(remote_config_file);
diff --git a/src/logging/log_daemon_config.c b/src/logging/log_daemon_config.c
index cf58e6230e..3226b2c484 100644
--- a/src/logging/log_daemon_config.c
+++ b/src/logging/log_daemon_config.c
@@ -73,6 +73,7 @@ virLogDaemonConfigNew(bool privileged ATTRIBUTE_UNUSED)
return NULL;
data->max_clients = 1024;
+ data->admin_max_clients = 5000;
data->max_size = 1024 * 1024 * 2;
data->max_backups = 3;
@@ -103,6 +104,8 @@ virLogDaemonConfigLoadOptions(virLogDaemonConfigPtr data,
return -1;
if (virConfGetValueUInt(conf, "max_clients", &data->max_clients)
< 0)
return -1;
+ if (virConfGetValueUInt(conf, "admin_max_clients",
&data->admin_max_clients) < 0)
+ return -1;
if (virConfGetValueSizeT(conf, "max_size", &data->max_size) < 0)
return -1;
if (virConfGetValueSizeT(conf, "max_backups", &data->max_backups)
< 0)
diff --git a/src/logging/log_daemon_config.h b/src/logging/log_daemon_config.h
index 72d77d5e6f..53101b0610 100644
--- a/src/logging/log_daemon_config.h
+++ b/src/logging/log_daemon_config.h
@@ -34,6 +34,7 @@ struct _virLogDaemonConfig {
char *log_filters;
char *log_outputs;
unsigned int max_clients;
+ unsigned int admin_max_clients;
size_t max_backups;
size_t max_size;
diff --git a/src/logging/test_virtlogd.aug.in b/src/logging/test_virtlogd.aug.in
index 3e6888fd48..ee3fae5cde 100644
--- a/src/logging/test_virtlogd.aug.in
+++ b/src/logging/test_virtlogd.aug.in
@@ -2,6 +2,8 @@ module Test_virtlogd =
let conf = "log_level = 3
log_filters=\"3:remote 4:event\"
log_outputs=\"3:syslog:virtlogd\"
+max_clients = 10
+admin_max_clients = 10
max_size = 131072
max_backups = 3
"
@@ -10,5 +12,7 @@ max_backups = 3
{ "log_level" = "3" }
{ "log_filters" = "3:remote 4:event" }
{ "log_outputs" = "3:syslog:virtlogd" }
+ { "max_clients" = "10" }
+ { "admin_max_clients" = "10" }
{ "max_size" = "131072" }
{ "max_backups" = "3" }
diff --git a/src/logging/virtlogd-admin.socket.in b/src/logging/virtlogd-admin.socket.in
new file mode 100644
index 0000000000..595e6c4c4b
--- /dev/null
+++ b/src/logging/virtlogd-admin.socket.in
@@ -0,0 +1,10 @@
+[Unit]
+Description=Virtual machine log manager socket
+Before=libvirtd.service
+
+[Socket]
+ListenStream=@localstatedir@/run/libvirt/virtlogd-admin-sock
+Service=virtlogd.service
+
+[Install]
+WantedBy=sockets.target
diff --git a/src/logging/virtlogd.aug b/src/logging/virtlogd.aug
index 5ed174230d..4fdcba72af 100644
--- a/src/logging/virtlogd.aug
+++ b/src/logging/virtlogd.aug
@@ -29,6 +29,7 @@ module Virtlogd =
| str_entry "log_outputs"
| int_entry "log_buffer_size"
| int_entry "max_clients"
+ | int_entry "admin_max_clients"
| int_entry "max_size"
| int_entry "max_backups"
diff --git a/src/logging/virtlogd.service.in b/src/logging/virtlogd.service.in
index aa9aa698b5..3d9ae36150 100644
--- a/src/logging/virtlogd.service.in
+++ b/src/logging/virtlogd.service.in
@@ -1,6 +1,7 @@
[Unit]
Description=Virtual machine log manager
Requires=virtlogd.socket
+Requires=virtlogd-admin.socket
Before=libvirtd.service
Documentation=man:virtlogd(8)
Documentation=https://libvirt.org
--
2.14.3